in src/cdi/adapter_socket.c [226:329]
static CdiReturnStatus SocketEndpointOpen(AdapterEndpointHandle endpoint_handle, const char* remote_address_str,
int port_number)
{
CdiReturnStatus ret = kCdiStatusOk;
// Create an Internet socket which will be used for writing or reading.
CdiSocket new_socket;
if (CdiOsSocketOpen(remote_address_str, port_number, &new_socket)) {
// Allocate memory in which to store socket endpoint specific state.
endpoint_handle->type_specific_ptr = (SocketEndpointState*)CdiOsMemAllocZero(sizeof(SocketEndpointState));
SocketEndpointState* private_state_ptr = (SocketEndpointState*)endpoint_handle->type_specific_ptr;
if (private_state_ptr == NULL) {
ret = kCdiStatusNotEnoughMemory;
} else {
// Save the now open file descriptor for use inside of receive thread or transmit function.
private_state_ptr->socket = new_socket;
private_state_ptr->destination_port_number = port_number;
if (endpoint_handle->adapter_con_state_ptr->direction == kEndpointDirectionReceive ||
endpoint_handle->adapter_con_state_ptr->direction == kEndpointDirectionBidirectional) {
bool pool_created = false;
bool thread_created = false;
// Create the receive thread shutdown signal.
bool signal_created = CdiOsSignalCreate(&private_state_ptr->shutdown);
if (!signal_created) {
CDI_LOG_THREAD(kLogError, "Failed to create socket receive thread shutdown signal.");
} else {
// Create a pool of ReceiveBufferRecord structures.
pool_created = CdiPoolCreateAndInitItems("socket receiver", RX_SOCKET_BUFFER_SIZE,
RX_SOCKET_BUFFER_SIZE_GROW, MAX_POOL_GROW_COUNT,
sizeof(ReceiveBufferRecord), true,
&private_state_ptr->receive_buffer_pool,
SocketEndpointPoolItemInit, NULL);
if (!pool_created) {
CDI_LOG_THREAD(kLogError, "Failed to allocate socket receive buffer pool.");
}
}
if (pool_created) {
// Start the receive thread.
thread_created = CdiOsThreadCreate(SocketReceiveThread, &private_state_ptr->receive_thread_id,
"socket receiver", endpoint_handle, NULL);
if (!thread_created) {
CDI_LOG_THREAD(kLogError, "Failed to start socket receive thread.");
}
}
// Make sure that everything got created. If not, clean up and return error.
if (!(signal_created && pool_created && thread_created)) {
CdiPoolDestroy(private_state_ptr->receive_buffer_pool); // Not set to NULL (freed below).
CdiOsSignalDelete(private_state_ptr->shutdown);
CdiOsSocketClose(new_socket);
ret = kCdiStatusAllocationFailed;
}
}
}
} else {
CDI_LOG_HANDLE(endpoint_handle->adapter_con_state_ptr->log_handle, kLogError,
"Failed to open socket on Destination Port[%d].", port_number);
ret = kCdiStatusOpenFailed;
}
if (kCdiStatusOk == ret && (endpoint_handle->adapter_con_state_ptr->direction == kEndpointDirectionSend ||
endpoint_handle->adapter_con_state_ptr->direction == kEndpointDirectionBidirectional)) {
// This small delay helps when using cdi_test to send to a receiver in the same invocation. No means of
// synchronizing between the transmitting and receiving connections is available so delaying the transmitter
// helps give the receiver a better chance of being ready before packets start flowing to it.
CdiOsSleep(50);
}
if (kCdiStatusOk == ret) {
CdiProtocolVersionNumber version = {
.version_num = 1,
.major_version_num = 0,
.probe_version_num = 0
};
if (endpoint_handle->cdi_endpoint_handle) {
EndpointManagerProtocolVersionSet(endpoint_handle->cdi_endpoint_handle, &version);
} else {
// The control interface does not have a cdi_endpoint_handle, so set the protocol version directly here.
ProtocolVersionSet(&version, &endpoint_handle->protocol_handle);
}
endpoint_handle->connection_status_code = kCdiConnectionStatusConnected;
if (endpoint_handle->adapter_con_state_ptr->data_state.connection_cb_ptr) {
// Notify application that we are connected.
CdiCoreConnectionCbData cb_data = {
.status_code = kCdiConnectionStatusConnected,
.err_msg_str = NULL,
.connection_user_cb_param = endpoint_handle->adapter_con_state_ptr->data_state.connection_user_cb_param
};
(endpoint_handle->adapter_con_state_ptr->data_state.connection_cb_ptr)(&cb_data);
}
} else {
// An error occurred, so free the private memory, if it was allocated.
if (endpoint_handle->type_specific_ptr) {
CdiOsMemFree(endpoint_handle->type_specific_ptr);
endpoint_handle->type_specific_ptr = NULL;
}
}
return ret;
}