axl_bool vortex_sequencer_direct_send (VortexConnection * connection, VortexChannel * channel, VortexWriterData * packet) { /* reply number */ axl_bool result = axl_true; #if defined(ENABLE_VORTEX_LOG) VortexCtx * ctx = vortex_connection_get_ctx (connection); #endif #if defined(ENABLE_VORTEX_LOG) /* send the frame */ if (vortex_log2_is_enabled (ctx)) vortex_log2 (VORTEX_LEVEL_DEBUG, "Sending message, size (%d) over channel=%d (%p), connection id=%d, errno=%d, Content: \n%s", packet->the_size, vortex_channel_get_number (channel), channel, vortex_connection_get_id (connection), errno, packet->the_frame); else vortex_log (VORTEX_LEVEL_DEBUG, "Sending message, size (%d) over channel=%d (%p), connection id=%d, errno=%d", packet->the_size, vortex_channel_get_number (channel), channel, vortex_connection_get_id (connection), errno); #endif if (! vortex_frame_send_raw (connection, packet->the_frame, packet->the_size)) { /* drop a log */ vortex_log (VORTEX_LEVEL_CRITICAL, "unable to send frame over connection id=%d: errno=(%d): %s", vortex_connection_get_id (connection), errno, vortex_errno_get_error (errno)); /* set as non connected and flag the result */ result = axl_false; } /* signal the message have been sent */ if ((packet->type == VORTEX_FRAME_TYPE_RPY || packet->type == VORTEX_FRAME_TYPE_NUL) && packet->is_complete && ! packet->fixed_more) { /* update reply sent */ vortex_channel_update_status (channel, 0, packet->msg_no, UPDATE_RPY_NO_WRITTEN); /* unblock waiting thread for replies sent */ vortex_channel_signal_reply_sent_on_close_blocked (channel); /* signal reply sent */ vortex_channel_signal_rpy_sent (channel, packet->msg_no); } /* nothing more */ return result; }
void frame_received (VortexChannel * channel, VortexConnection * connection, VortexFrame * frame, axlPointer user_data) { int iterator = 10; printf ("A frame received on channl: %d\n", vortex_channel_get_number (channel)); printf ("Data received: '%s'\n", (char*) vortex_frame_get_payload (frame)); /* reply the peer client with the same content 10 times */ while (iterator >= 0) { printf ("Sending the reply..\n"); if (! vortex_channel_send_ans_rpyv (channel, vortex_frame_get_msgno (frame), "Received Ok(%d): %s", iterator, vortex_frame_get_payload (frame))) { fprintf (stderr, "There was an error while sending the reply message"); } printf ("Reply: %d sent..\n", iterator); iterator--; } /* send the last reply. */ if (!vortex_channel_finalize_ans_rpy (channel, vortex_frame_get_msgno (frame))) { fprintf (stderr, "There was an error while sending the NUL reply message"); } printf ("VORTEX_LISTENER: end task (pid: %d)\n", getpid ()); return; }
axl_bool vortex_sequencer_remove_message_sent (VortexCtx * ctx, VortexChannel * channel) { VortexSequencerData * data; axl_bool is_empty; /* get pending message */ data = vortex_channel_remove_pending_message (channel); if (data == NULL) return axl_true; /* is_empty=axl_true : notify caller that this channel has nothing to send anymore */ /* get if the queue is empty */ is_empty = (vortex_channel_next_pending_message (channel) == NULL); /* log here */ vortex_log (VORTEX_LEVEL_DEBUG, "Last message on channel=%d (%p) was sent completly, pending messages: %d (%d)", vortex_channel_get_number (channel), channel, vortex_channel_pending_messages (channel), is_empty); /* release a reference */ /* vortex_channel_unref (channel); */ /* release feeder */ vortex_payload_feeder_unref (data->feeder); /* release data */ axl_free (data->message); axl_free (data); return is_empty; }
/** * @internal * * @brief Internal function that allows the vortex reader to * re-sequence messages that are hold due to channel being stalled * * @param channel The channel to notify */ void vortex_sequencer_signal_update (VortexChannel * channel, VortexConnection * connection) { /* get current context */ VortexCtx * ctx = vortex_channel_get_ctx (channel); VortexSequencerState * state; vortex_log (VORTEX_LEVEL_DEBUG, "about to check for pending queue messages=%d not sequenced for channel=%d (%p)", vortex_channel_pending_messages (channel), vortex_channel_get_number (channel), channel); /* check if we have data to be resequenced */ if (vortex_channel_next_pending_message (channel)) { /* get reference to the state */ state = ctx->sequencer_state; /* move to ready */ vortex_mutex_lock (&state->mutex); if (! axl_hash_get (state->ready, channel)) { /* update channel reference */ if (! vortex_channel_ref2 (channel, "sequencer")) { vortex_log (VORTEX_LEVEL_CRITICAL, "unable to acquire channel %p reference, failed to to signal sequencer for SEQ frame update", channel); vortex_mutex_unlock (&state->mutex); return; } /* end if */ /* insert hash */ axl_hash_insert_full (state->ready, channel, (axlDestroyFunc) __vortex_sequencer_channel_unref, INT_TO_PTR (1), NULL); } /* end if */ /* signal */ vortex_cond_signal (&state->cond); vortex_mutex_unlock (&state->mutex); }else { vortex_log (VORTEX_LEVEL_DEBUG, "there is no messages pending to be sequenced, over the channel=%d", vortex_channel_get_number (channel)); } /* end if */ return; }
void frame_received (VortexChannel * channel, VortexConnection * connection, VortexFrame * frame, axlPointer user_data) { printf ("VORTEX_LISTENER: STARTED (pid: %d)\n", getpid ()); printf ("A frame received on channl: %d\n", vortex_channel_get_number (channel)); printf ("Data received: '%s'\n", (char*) vortex_frame_get_payload (frame)); /* reply */ vortex_channel_send_rpy (channel, "I have received you message, thanks..", 37, vortex_frame_get_msgno (frame)); printf ("VORTEX_LISTENER: CLOSE CHANNEL (pid: %d)\n", getpid ()); /* close the channel */ vortex_channel_close (channel, NULL); printf ("VORTEX_LISTENER: FINSHED (pid: %d)\n", getpid ()); return; }
void frame_received (VortexChannel * channel, VortexConnection * connection, VortexFrame * frame, axlPointer user_data) { VortexAsyncQueue * queue; int iterator = 0; printf ("A frame received on channl: %d\n", vortex_channel_get_number (channel)); printf ("Data received: '%s'\n", (char*) vortex_frame_get_payload (frame)); if (vortex_frame_get_type (frame) == VORTEX_FRAME_TYPE_MSG) { /* send back a series of replies */ queue = vortex_async_queue_new (); while (iterator < 100) { /* wait during 50ms */ vortex_async_queue_timedpop (queue, 50000); /* send a reply */ vortex_channel_send_ans_rpy (channel, "This is a reply to the message", 30, vortex_frame_get_msgno (frame)); /* next message */ iterator++; } /* send NUL */ vortex_channel_finalize_ans_rpy (channel, vortex_frame_get_msgno (frame)); } printf ("VORTEX_LISTENER: end task (pid: %d)\n", getpid ()); return; }
void vortex_sequencer_process_channels (VortexCtx * ctx, VortexSequencerState * state, axl_bool process_channel_0) { axl_bool paused; axl_bool complete; axl_bool is_empty; axl_bool is_stalled; VortexChannel * channel = NULL; VortexConnection * conn = NULL; /* now iterate all ready channels */ axl_hash_cursor_first (state->ready_cursor); while (axl_hash_cursor_has_item (state->ready_cursor)) { /* get the channel and manage it, unlocking * during the process */ channel = axl_hash_cursor_get_key (state->ready_cursor); /* check for remove flag */ if (PTR_TO_INT (vortex_channel_get_data (channel, "vo:seq:del"))) { axl_hash_cursor_remove (state->ready_cursor); continue; } /* check if channel is stalled */ if (vortex_channel_is_stalled (channel)) { vortex_log (VORTEX_LEVEL_DEBUG, "channel=%d (%p) is stalled, removing from ready set", vortex_channel_get_number (channel), channel); axl_hash_cursor_remove (state->ready_cursor); continue; } /* end if */ /* check what kind of channel is this to know if we * have to process it */ if (process_channel_0 && vortex_channel_get_number (channel) != 0) { axl_hash_cursor_next (state->ready_cursor); continue; } if (!process_channel_0 && vortex_channel_get_number (channel) == 0) { axl_hash_cursor_next (state->ready_cursor); continue; } /* get connection reference */ conn = vortex_channel_get_connection (channel); /* acquire connection */ if (! vortex_connection_ref (conn, "vortex-sequencer")) { vortex_log (VORTEX_LEVEL_CRITICAL, "Unable to acquire reference to the connection (%p) inside vortex sequencer to do sending round, dropping channel (%p)", conn, channel); axl_hash_cursor_remove (state->ready_cursor); continue; } /* end if */ vortex_log (VORTEX_LEVEL_DEBUG, "handling next send channel=%d (%p), conn-id=%d (%p)", vortex_channel_get_number (channel), channel, vortex_connection_get_id (conn), conn); /* unlock and call */ vortex_mutex_unlock (&state->mutex); /* call to do send operation */ paused = axl_false; complete = axl_false; is_empty = axl_false; __vortex_sequencer_do_send_round (ctx, channel, conn, &paused, &complete); vortex_log (VORTEX_LEVEL_DEBUG, "it seems the message was sent completely over conn-id=%d, channel=%d (%p)", vortex_connection_get_id (conn), vortex_channel_get_number (channel), channel); /* release connection (unlock mutex to allow * connection close process to reenter into * sequencer module) */ vortex_connection_unref (conn, "vortex-sequencer"); vortex_mutex_lock (&state->mutex); /* remove message sent */ is_stalled = vortex_channel_is_stalled (channel); if (complete) { /* remove message sent */ is_empty = vortex_sequencer_remove_message_sent (ctx, channel); } /* end if */ /* check for remove flag */ if (PTR_TO_INT (vortex_channel_get_data (channel, "vo:seq:del"))) { axl_hash_cursor_remove (state->ready_cursor); continue; } /* check channel after send operation */ if (is_empty) { vortex_log (VORTEX_LEVEL_DEBUG, "Channel %p is empty (no more pending messages), removing from sequencer", channel); /* no more send operations, remove channel from our registry but check * first it wasn't removed during the unlock */ axl_hash_cursor_remove (state->ready_cursor); continue; } /* now check stalled channel */ if (is_stalled || paused) { vortex_log (VORTEX_LEVEL_DEBUG, "Channel %p is stalled or paused, removing from sequencer", channel); /* no more send operations, remove channel from our registry but check * first it wasn't removed during the unlock */ axl_hash_cursor_remove (state->ready_cursor); continue; } /* end if */ /* next item */ axl_hash_cursor_next (state->ready_cursor); } /* end while */ return; }
/** * @internal Function that does a send round for a channel. The * function assumes the channel is not stalled (but can end stalled * after the function finished). * */ void __vortex_sequencer_do_send_round (VortexCtx * ctx, VortexChannel * channel, VortexConnection * conn, axl_bool * paused, axl_bool * complete) { VortexSequencerData * data; #if defined(ENABLE_VORTEX_LOG) int message_size; int max_seq_no = 0; #endif int size_to_copy; VortexWriterData packet; /* get data from channel */ data = vortex_channel_next_pending_message (channel); if (data == NULL) { /* no pending message on this channel */ vortex_log (VORTEX_LEVEL_DEBUG, "no data were found to sequence on this channel, remove channel"); return; } vortex_log (VORTEX_LEVEL_DEBUG, "a new message to be sequenced: (conn-id=%d, channel=%d, size=%d)..", vortex_connection_get_id (conn), data->channel_num, data->message_size); /* if feeder is defined, get pending message size */ if (data->feeder) data->message_size = vortex_payload_feeder_get_pending_size (data->feeder); /* refresh all sending data */ data->first_seq_no = vortex_channel_get_next_seq_no (channel); #if defined(ENABLE_VORTEX_LOG) message_size = data->message_size; max_seq_no = vortex_channel_get_max_seq_no_remote_accepted (channel); #endif vortex_log (VORTEX_LEVEL_DEBUG, "sequence operation (%p): type=%d, msgno=%d, next seq no=%u message size=%d max seq no=%u step=%u", data, data->type, data->msg_no, data->first_seq_no, message_size, max_seq_no, data->step); /* build the packet to send */ size_to_copy = vortex_sequencer_build_packet_to_send (ctx, channel, conn, data, &packet); *complete = packet.is_complete; /* check if the transfer is cancelled or paused */ if (size_to_copy < 0) { *paused = axl_true; return; } /* STEP 1: now queue the rest of the message if it wasn't * completly sequence. We do this before sending the frame to * avoid a possible race condition between sending the message * sequenced, be processed at the remote side, the remote side * generate a SEQ frame, send it, and our vortex reader * process it, finding that there is not pending, not yet * completely sequenced message. * * Incredible, but true! */ if (! packet.is_complete) { /* well, it seems we didn't be able to send the hole * message, so there are some remaining bytes. Just * keep track about how many bytes we have sent. We * will used this information once the message is * enabled to be sent again on the next SEQ * received. */ data->step = data->step + size_to_copy; /* make next seq no value to point to the next byte to send */ data->first_seq_no = (data->first_seq_no + size_to_copy) % (MAX_SEQ_NO); /* make message size to be decreased the amount of bytes sent. */ data->message_size = data->message_size - size_to_copy; vortex_log (VORTEX_LEVEL_DEBUG, "updating message sequencing status: next seq no=%u max seq no accepted=%u message size=%d step=%u", data->first_seq_no, max_seq_no, data->message_size, data->step); vortex_log (VORTEX_LEVEL_DEBUG, "the message sequenced is not going to be sent completely (%d != %d)", size_to_copy, message_size); } /* end if */ /* because we have sent the message, update remote seqno buffer used */ vortex_channel_update_status (channel, size_to_copy, 0, UPDATE_SEQ_NO); /* STEP 2: now, send the package built, queueing it at the * channel queue. At this point, we have prepared the rest to * be sequenced message. */ /* now, perform a send operation for the frame built */ vortex_log (VORTEX_LEVEL_DEBUG, "frame built, send the frame directly (over channel=%d, conn-id=%d)", vortex_channel_get_number (channel), vortex_connection_get_id (conn)); if (! vortex_sequencer_direct_send (conn, channel, &packet)) { vortex_log (VORTEX_LEVEL_WARNING, "unable to send data at this moment"); return; } /* that's all vortex sequencer process can do */ return; }
int vortex_sequencer_build_packet_to_send (VortexCtx * ctx, VortexChannel * channel, VortexConnection * conn, VortexSequencerData * data, VortexWriterData * packet) { int size_to_copy = 0; unsigned int max_seq_no_accepted = vortex_channel_get_max_seq_no_remote_accepted (channel); char * payload = NULL; /* clear packet */ memset (packet, 0, sizeof (VortexWriterData)); /* flag as not complete until something different is set */ packet->is_complete = axl_false; /* check particular case where an empty message is to be sent * and the message is NUL */ if (data->message_size == 0 && data->type == VORTEX_FRAME_TYPE_NUL) goto build_frame; /* calculate how many bytes to copy from the payload * according to max_seq_no */ size_to_copy = vortex_channel_get_next_frame_size (channel, data->first_seq_no, data->message_size, max_seq_no_accepted); /* check that the next_frame_size do not report wrong values */ if (size_to_copy > data->message_size || size_to_copy <= 0) { __vortex_connection_shutdown_and_record_error ( conn, VortexProtocolError, "vortex_channel_get_next_frame_size is reporting wrong values (size to copy: %d > message size: %d), this will cause protocol failures...shutdown connection id=%d (channel stalled: %d)", size_to_copy, data->message_size, vortex_connection_get_id (conn), vortex_channel_is_stalled (channel)); return 0; } /* check here if we have a feeder defined */ if (data->feeder) { if (data->feeder->status == 0) { /* check and increase buffer */ CHECK_AND_INCREASE_BUFFER (size_to_copy, ctx->sequencer_feeder_buffer, ctx->sequencer_feeder_buffer_size); /* get content available at this moment to be sent */ size_to_copy = vortex_payload_feeder_get_content (data->feeder, size_to_copy, ctx->sequencer_feeder_buffer); } else { vortex_log (VORTEX_LEVEL_DEBUG, "feeder cancelled, close transfer status is: %d", data->feeder->close_transfer); if (! data->feeder->close_transfer) { /* also record current msgno to continue in the future */ data->feeder->msg_no = data->msg_no; /* remove queued request if found same pointer */ if (data == vortex_channel_next_pending_message (channel)) { /* remove the queued request but ensure we are the only thread touching this */ vortex_sequencer_remove_message_sent (ctx, channel); } /* signal caller to stop delivering this content */ return -1; } /* end if */ /* flag this feeder is about being cancelled/paused */ size_to_copy = -1; } /* end if */ } /* end if */ vortex_log (VORTEX_LEVEL_DEBUG, "the channel=%d (on conn-id=%d) is not stalled, continue with sequencing, about to send (size_to_copy:%d) bytes as payload (buffer:%d)...", vortex_channel_get_number (channel), vortex_connection_get_id (vortex_channel_get_connection (channel)), size_to_copy, ctx->sequencer_send_buffer_size); vortex_log (VORTEX_LEVEL_DEBUG, "channel remote max seq no accepted: %u (proposed: %u)...", vortex_channel_get_max_seq_no_remote_accepted (channel), max_seq_no_accepted); /* create the new package to be managed by the vortex writer */ packet->msg_no = data->msg_no; if (size_to_copy > 0) { /* check if we have to realloc buffer */ CHECK_AND_INCREASE_BUFFER (size_to_copy, ctx->sequencer_send_buffer, ctx->sequencer_send_buffer_size); } /* we have the payload on buffer */ build_frame: /* set datatype for this package */ packet->type = data->type; /* report what we are going to sequence */ vortex_log (VORTEX_LEVEL_DEBUG, "sequencing next message: type=%d, channel num=%d, msgno=%d, more=%d, next seq=%u size=%d ansno=%d", data->type, data->channel_num, data->msg_no, !(data->message_size == size_to_copy), data->first_seq_no, size_to_copy, data->ansno); vortex_log (VORTEX_LEVEL_DEBUG, " message=%p, step=%u, message-size=%u", data->message, data->step, data->message_size); /* point to payload */ if (data->feeder) { payload = (size_to_copy > 0) ? ctx->sequencer_feeder_buffer : NULL; } else payload = (data->message != NULL) ? (data->message + data->step) : NULL; /* check if the packet is complete (either last frame or all * the payload fits into a single frame */ if (data->feeder) { /* prepare is complete flag */ packet->is_complete = (data->feeder->status != 0 && data->feeder->close_transfer) ? axl_true : vortex_payload_feeder_is_finished (data->feeder); /* normalize size_to_copy to avoid the caller to skipp ending this empty frame */ if (size_to_copy < 0) size_to_copy = 0; } else packet->is_complete = (size_to_copy == data->message_size); /* build frame */ packet->the_frame = vortex_frame_build_up_from_params_s_buffer ( data->type, /* frame type to be created */ data->channel_num, /* channel number the frame applies to */ data->msg_no, /* the message number */ /* frame payload size to be created */ !packet->is_complete || data->fixed_more, /* have more frames */ data->first_seq_no, /* sequence number for the frame to be created */ /* size for the payload starting from previous sequence number */ size_to_copy, /* an optional ansno value, only used for ANS frames */ data->ansno, /* no mime configuration, already handled from vortex channel module */ NULL, /* no mime configuration for transfer encoding, * already handler by vortex channel module */ NULL, /* the frame payload itself */ payload, /* calculated frame size */ &(packet->the_size), /* buffer and its size */ ctx->sequencer_send_buffer, ctx->sequencer_send_buffer_size); /* update fixed more flag on packet */ packet->fixed_more = data->fixed_more; /* return size used from the entire message */ return size_to_copy; }
/** * @brief a frame received Callback */ void listenerFrameReceivedCallback (VortexChannel* channel, VortexConnection* connection, VortexFrame* frame, axlPointer user_data) { VORTEXListenerFrameReceivedCallbackData* callbackData = (VORTEXListenerFrameReceivedCallbackData*) user_data; TML_INT32 iRet = TML_SUCCESS; ///////////////////////////////////////////////////////////////////////////// // Fetching all necessary attributes from Vortex: /////////////////////////// // Die Connection ID: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_connection_get_id"); int iConnectionID = vortex_connection_get_id(connection); /////////////////////////// // Die Host IP: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_connection_get_host_ip"); const char* sHostIP = vortex_connection_get_host_ip(connection); /////////////////////////// // Der Port: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_connection_get_local_port"); const char* sPort = vortex_connection_get_port(connection); /////////////////////////// // Die Channel ID: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_channel_get_number"); int iChannelID = vortex_channel_get_number (channel); if (-1 == iChannelID) iRet = TML_ERR_LISTENER_COMMUNICATION; /////////////////////////// // Die Message ID: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_frame_get_msgno"); int iMsgID = vortex_frame_get_msgno (frame); if (-1 == iMsgID) iRet = TML_ERR_LISTENER_COMMUNICATION; /////////////////////////// // Das Profil, mit dem der Sender conneted ist: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_channel_get_profile"); const char* sProfile = vortex_channel_get_profile (channel); if (NULL == sProfile) iRet = TML_ERR_LISTENER_COMMUNICATION; /////////////////////////// // Das Payload: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_frame_get_payload"); char* cPayload = (char*)vortex_frame_get_payload (frame); if (NULL == cPayload) iRet = TML_ERR_LISTENER_COMMUNICATION; /////////////////////////// // Die Payloadsize: callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_frame_get_payload_size"); int iPayloadSize = vortex_frame_get_payload_size (frame); if (-1 == iPayloadSize) iRet = TML_ERR_LISTENER_COMMUNICATION; ///////////////////////////////////////////////////////////////////////////// // Set all necessary Vortex attributes into the TML_COMMAND_HANDLE Obj: if (TML_SUCCESS == iRet){ // A new TML_COMMAND_HANDLE object out of the payload: TML_COMMAND_HANDLE cmdHandle; iRet = tml_Cmd_Create(&cmdHandle); if (TML_SUCCESS == iRet){ SIDEX_HANDLE sHandle; /////////////////////////////////////////////// // Acquire critical section use: tml_Cmd_Acquire_Sidex_Handle(cmdHandle, &sHandle); iRet = sidex_Set_Content(sHandle, cPayload); /////////////////////////////////////////////// // Now I can release the critical section use: tml_Cmd_Release_Sidex_Handle(cmdHandle); } if (TML_SUCCESS == iRet){ // Vortex- session ID into the TML_COMMAND_HANDLE object: tml_Cmd_Attr_Set_Session_ID(cmdHandle, iConnectionID); // Don't mind of return value // Vortex- channel ID into the TML_COMMAND_HANDLE object: tml_Cmd_Attr_Set_Channel_ID(cmdHandle, iChannelID); // Don't mind of return value callbackData->pLog->log (TML_LOG_VORTEX_CMD, "TMLCoreListener", "listenerFrameReceivedCallback", "Vortex CMD", "vortex_channel_ref"); vortex_channel_ref(channel); // I will be shure to have a valid channel until the reply is send // Vortex- channel into the TML_COMMAND_HANDLE object: tml_Cmd_Attr_Set_Channel(cmdHandle, channel); // Don't mind of return value // Vortex- message ID into the TML_COMMAND_HANDLE object: tml_Cmd_Attr_Set_Message_ID(cmdHandle, iMsgID); // Don't mind of return value // Vortex- profile into the TML_COMMAND_HANDLE object: tml_Cmd_Attr_Set_Profile(cmdHandle, sProfile); // The core handle: tml_Cmd_Attr_Set_Core_Reference(cmdHandle, callbackData->tmlcorehandle); // Don't mind of return value TML_CONNECTION_HANDLE connectionHandle = TML_HANDLE_TYPE_NULL; ////////////////////////////////////////////////////////////////// // Add the connection to the list: if (NULL != sHostIP && NULL != sPort && NULL != connection){ ((tmlCoreWrapper*)callbackData->tmlcorehandle)->tmlCoreWrapper_Connect(sHostIP, sPort, false, &connectionHandle, connection); ((tmlObjWrapper*)cmdHandle)->tmlObjWrapper_Set_Connection(connectionHandle); } // Now call the callback method: globalCallback(callbackData->callback, (void*) cmdHandle); } } else{ callbackData->pLog->log ("TMLCoreListener", "listenerFrameReceivedCallback", "ERROR", "Problem on getting some attributes."); } return; }