static void * handle_packets(void *arg) { #ifdef _WIN32 SOCKET *fdp; #else int *fdp; #endif char *dump_buf; ssize_t length; char buf[MAX_PACKET_SIZE]; #ifdef _WIN32 fdp = (SOCKET *)arg; #else fdp = (int *)arg; #endif for (;;) { length = recv(*fdp, buf, MAX_PACKET_SIZE, 0); if (length > 0) { if ((dump_buf = usrsctp_dumppacket(buf, (size_t)length, SCTP_DUMP_INBOUND)) != NULL) { fprintf(stderr, "%s", dump_buf); usrsctp_freedumpbuffer(dump_buf); } usrsctp_conninput(fdp, buf, (size_t)length, 0); } } return (NULL); }
static int conn_output(void *addr, void *buf, size_t length, uint8_t tos, uint8_t set_df) { char *dump_buf; #ifdef _WIN32 SOCKET *fdp; #else int *fdp; #endif #ifdef _WIN32 fdp = (SOCKET *)addr; #else fdp = (int *)addr; #endif if ((dump_buf = usrsctp_dumppacket(buf, length, SCTP_DUMP_OUTBOUND)) != NULL) { //fprintf(stderr, "%s", dump_buf); usrsctp_freedumpbuffer(dump_buf); } #ifdef _WIN32 if (send(*fdp, buf, (int)length, 0) == SOCKET_ERROR) { return (WSAGetLastError()); #else if (send(*fdp, buf, length, 0) < 0) { return (errno); #endif } else { return (0); } } static int receive_cb(struct socket *sock, union sctp_sockstore addr, void *data, size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info) { printf("Message %p received on sock = %p.\n", data, (void *)sock); if (data) { if ((flags & MSG_NOTIFICATION) == 0) { printf("Messsage of length %d received via %p:%u on stream %u with SSN %u and TSN %u, PPID %u, context %u, flags %x.\n", (int)datalen, addr.sconn.sconn_addr, ntohs(addr.sconn.sconn_port), rcv.rcv_sid, rcv.rcv_ssn, rcv.rcv_tsn, ntohl(rcv.rcv_ppid), rcv.rcv_context, flags); } free(data); } else { usrsctp_deregister_address(ulp_info); usrsctp_close(sock); } return (1); }
static DWORD WINAPI #else static void * #endif handle_packets(void *arg) { #ifdef _WIN32 SOCKET *fdp; #else int *fdp; #endif char *dump_buf; ssize_t length; char buf[MAX_PACKET_SIZE]; #ifdef _WIN32 fdp = (SOCKET *)arg; #else fdp = (int *)arg; #endif for (;;) { #if defined(__NetBSD__) pthread_testcancel(); #endif length = recv(*fdp, buf, MAX_PACKET_SIZE, 0); if (length > 0) { if ((dump_buf = usrsctp_dumppacket(buf, (size_t)length, SCTP_DUMP_INBOUND)) != NULL) { fprintf(stderr, "%s", dump_buf); usrsctp_freedumpbuffer(dump_buf); } usrsctp_conninput(fdp, buf, (size_t)length, 0); } } #ifdef _WIN32 return 0; #else return (NULL); #endif }
static int conn_output(void *addr, void *buf, size_t length, uint8_t tos, uint8_t set_df) { char *dump_buf; #ifdef _WIN32 SOCKET *fdp; #else int *fdp; #endif #ifdef _WIN32 fdp = (SOCKET *)addr; #else fdp = (int *)addr; #endif if ((dump_buf = usrsctp_dumppacket(buf, length, SCTP_DUMP_OUTBOUND)) != NULL) { fprintf(stderr, "%s", dump_buf); usrsctp_freedumpbuffer(dump_buf); } #ifdef _WIN32 if (send(*fdp, buf, (int)length, 0) == SOCKET_ERROR) { return (WSAGetLastError()); #else if (send(*fdp, buf, length, 0) < 0) { return (errno); #endif } else { return (0); } } static int receive_cb(struct socket *s, union sctp_sockstore addr, void *data, size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info) { if (data) { if (flags & MSG_NOTIFICATION) { printf("Notification of length %d received.\n", (int)datalen); } else { printf("Msg of length %d received via %p:%u on stream %u with SSN %u and TSN %u, PPID %u, context %u.\n", (int)datalen, addr.sconn.sconn_addr, ntohs(addr.sconn.sconn_port), rcv.rcv_sid, rcv.rcv_ssn, rcv.rcv_tsn, ntohl(rcv.rcv_ppid), rcv.rcv_context); } free(data); } else { usrsctp_close(s); } return (1); } void debug_printf(const char *format, ...) { va_list ap; va_start(ap, format); vprintf(format, ap); va_end(ap); }
void *janus_sctp_thread(void *data) { janus_sctp_association *sctp = (janus_sctp_association *)data; if(sctp == NULL) { JANUS_LOG(LOG_ERR, "Invalid SCTP association, closing thread\n"); g_thread_unref(g_thread_self()); return NULL; } JANUS_LOG(LOG_INFO, "[%"SCNu64"] Starting thread for SCTP association\n", sctp->handle_id); janus_sctp_message *message = NULL; gboolean sent_data = FALSE; while(sctp->dtls != NULL && sctp_running) { /* Anything to do at all? */ janus_mutex_lock(&sctp->mutex); if(!sctp->ready || (g_queue_is_empty(sctp->in_messages) && g_queue_is_empty(sctp->out_messages))) { janus_mutex_unlock(&sctp->mutex); g_usleep (10000); continue; } /* Check incoming messages */ if(!g_queue_is_empty(sctp->in_messages) && sent_data) { while(!g_queue_is_empty(sctp->in_messages)) { message = g_queue_pop_head(sctp->in_messages); if(message == NULL) continue; #ifdef DEBUG_SCTP if(sctp->debug_dump != NULL) { /* Dump incoming message */ char *dump = usrsctp_dumppacket(message->buffer, message->length, SCTP_DUMP_INBOUND); if(dump != NULL) { fwrite(dump, sizeof(char), strlen(dump), sctp->debug_dump); fflush(sctp->debug_dump); usrsctp_freedumpbuffer(dump); } } #endif /* Pass this data to the SCTP association */ janus_mutex_unlock(&sctp->mutex); usrsctp_conninput((void *)sctp, message->buffer, message->length, 0); janus_mutex_lock(&sctp->mutex); janus_sctp_message_destroy(message); message = NULL; } } /* Check outgoing messages */ if(sctp->dtls == NULL) { /* No DTLS stack anymore, we're done */ janus_mutex_unlock(&sctp->mutex); break; } if(!g_queue_is_empty(sctp->out_messages)) { while(!g_queue_is_empty(sctp->out_messages)) { message = g_queue_pop_head(sctp->out_messages); if(message == NULL) continue; #ifdef DEBUG_SCTP if(sctp->debug_dump != NULL) { /* Dump incoming message */ char *dump = usrsctp_dumppacket(message->buffer, message->length, SCTP_DUMP_OUTBOUND); if(dump != NULL) { fwrite(dump, sizeof(char), strlen(dump), sctp->debug_dump); fflush(sctp->debug_dump); usrsctp_freedumpbuffer(dump); } } #endif /* Encapsulate this data in DTLS and send it */ janus_dtls_send_sctp_data((janus_dtls_srtp *)sctp->dtls, message->buffer, message->length); janus_sctp_message_destroy(message); message = NULL; if(!sent_data) sent_data = TRUE; } } janus_mutex_unlock(&sctp->mutex); } JANUS_LOG(LOG_INFO, "[%"SCNu64"] Leaving SCTP association thread\n", sctp->handle_id); /* This association has been destroyed, wait a bit and then free all the resources */ g_usleep (1*G_USEC_PER_SEC); g_queue_free(sctp->in_messages); sctp->in_messages = NULL; g_queue_free(sctp->out_messages); sctp->out_messages = NULL; sctp->thread = NULL; #ifdef DEBUG_SCTP if(sctp->debug_dump != NULL) fclose(sctp->debug_dump); sctp->debug_dump = NULL; #endif g_free(sctp); sctp = NULL; g_thread_unref(g_thread_self()); return NULL; }