/**@internal * * Create a reactor object using given message port. * * Allocate and initialize the instance of su_root_t. Note that this * function always uses a reference to su_port_t, even when creating the * root fails. * * @param magic pointer to user data * @param port pointer to a message port * * @return A pointer to allocated su_root_t instance, NULL on error. */ su_root_t *su_root_create_with_port(su_root_magic_t *magic, su_port_t *port) { su_root_t *self; if (!port) return NULL; self = su_salloc(su_port_home(port), sizeof(struct su_root_s)); if (self) { self->sur_magic = magic; #if SU_HAVE_PTHREADS self->sur_threading = SU_HAVE_PTHREADS; #else self->sur_threading = 0; #endif /* This one creates a new reference to port */ su_task_new(self->sur_task, self, port); /* ... so we zap the old one below */ } su_port_decref(port, "su_root_create_with_port"); return self; }
int su_base_port_start_shared(su_root_t *parent, su_clone_r return_clone, su_root_magic_t *magic, su_root_init_f init, su_root_deinit_f deinit) { su_port_t *self = parent->sur_task->sut_port; su_root_t *child; child = su_salloc(su_port_home(self), sizeof *child); if (!child) return -1; child->sur_magic = magic; child->sur_deinit = deinit; child->sur_threading = parent->sur_threading; SU_TASK_COPY(child->sur_parent, su_root_task(parent), su_base_port_clone_start); SU_TASK_COPY(child->sur_task, child->sur_parent, su_base_port_clone_start); child->sur_task->sut_root = child; if (su_msg_create(return_clone, child->sur_task, su_root_task(parent), su_base_port_clone_break, 0) == 0 && init(child, magic) == 0) return 0; su_msg_destroy(return_clone); su_root_destroy(child); return -1; }
/** Print a SDP description. * * Encode the contents of the SDP session structure #sdp_session_t * to the @a msgbuf. The @a msgbuf has size @a msgsize * bytes. If @a msgbuf is @c NULL, the sdp_print() function allocates the * required buffer from the @a home heap. * * @param home Memory home (may be NULL). * @param session SDP session description structure to be encoded. * @param msgbuf Buffer to which encoding is stored (may be NULL). * @param msgsize Size of @a msgbuf. * @param flags Flags specifying the encoding options. * * The @a flags specify encoding options as follows: * * @li #sdp_f_strict - Printer should only emit messages conforming strictly * to the * specification. * * @li #sdp_f_realloc - If this flag is specified, and @a msgbuf is too * small for the resulting SDP message, @c sdp_print() may allocate a new * buffer for it from the heap. * * @li #sdp_f_print_prefix - The buffer provided by caller already contains * valid data. The result will concatenated to the string in the buffer. * * @li #sdp_f_mode_always - Always add mode attributes to media * * @li #sdp_f_mode_manual - Do not generate mode attributes * * @return * Always return a handle to an #sdp_printer_t object. * * @sa #sdp_printer_t, #sdp_session_t, sdp_printing_error(), * sdp_message(), sdp_message_size(), sdp_printer_free(), * sdp_parse(). */ sdp_printer_t *sdp_print(su_home_t *home, sdp_session_t const *session, char msgbuf[], isize_t msgsize, int flags) { sdp_printer_t *p = su_salloc(home, sizeof(*p)); if (p) { p->pr_size = sizeof(p); p->pr_home = home; p->pr_used = 0; if (msgbuf) { p->pr_may_realloc = (flags & sdp_f_realloc) != 0; p->pr_buffer = msgbuf; p->pr_bsiz = msgsize; if (flags & sdp_f_print_prefix) p->pr_used = strlen(msgbuf); } else { p->pr_owns_buffer = 1; p->pr_buffer = su_alloc(home, SDP_BLOCK); p->pr_bsiz = SDP_BLOCK; } p->pr_strict = (flags & sdp_f_strict) != 0; p->pr_all_rtpmaps = (flags & sdp_f_all_rtpmaps) != 0; p->pr_mode_manual = (flags & sdp_f_mode_manual) != 0; p->pr_mode_always = (flags & sdp_f_mode_always) != 0; if (session) print_session(p, session); else printing_error(p, "NULL session description"); return p; } else { return &printer_memory_error; } }
/** Convert session mode as #sdp_attribute_t structure. */ sdp_attribute_t *sdp_attribute_by_mode(su_home_t *home, sdp_mode_t mode) { sdp_attribute_t *a; char const *name; if (mode == sdp_inactive) name = "inactive"; else if (mode == sdp_sendonly) name = "sendonly"; else if (mode == sdp_recvonly) name = "recvonly"; else if (mode == sdp_sendrecv) name = "sendrecv"; else return NULL; a = su_salloc(home, sizeof(*a)); if (a) a->a_name = name; return a; }
/** Main function for clone thread. * * @internal */ static void *su_pthread_port_clone_main(void *varg) { struct clone_args *arg = (struct clone_args *)varg; su_task_r task; int zap = 1; #if SU_HAVE_WINSOCK su_init(); #endif task->sut_port = arg->create(); if (task->sut_port) { task->sut_root = su_salloc(su_port_home(task->sut_port), sizeof *task->sut_root); if (task->sut_root) { task->sut_root->sur_threading = 1; /* By default */ SU_TASK_COPY(task->sut_root->sur_parent, su_root_task(arg->parent), su_pthread_port_clone_main); SU_TASK_COPY(task->sut_root->sur_task, task, su_pthread_port_clone_main); if (su_msg_create(arg->clone, task, su_root_task(arg->parent), su_pthread_port_clone_break, 0) == 0) { task->sut_root->sur_magic = arg->magic; task->sut_root->sur_deinit = arg->deinit; su_root_set_max_defer(task->sut_root, su_root_get_max_defer(arg->parent)); if (arg->init(task->sut_root, arg->magic) == 0) { su_pthread_port_return_to_parent(arg, 0), arg = NULL; su_root_run(task->sut_root); /* Do the work */ /* Cleanup */ if (task->sut_port->sup_waiting_parent) { struct su_pthread_port_waiting_parent *mom; mom = task->sut_port->sup_waiting_parent; pthread_mutex_lock(mom->mutex); mom->waiting = 0; pthread_cond_signal(mom->cv); pthread_mutex_unlock(mom->mutex); pthread_mutex_lock(mom->deinit); su_port_getmsgs(task->sut_port); pthread_mutex_unlock(mom->deinit); } else zap = 0; } else su_msg_destroy(arg->clone); su_root_destroy(task->sut_root); } } task->sut_port->sup_base->sup_vtable-> su_port_decref(task->sut_port, zap, "su_pthread_port_clone_main"); } #if SU_HAVE_WINSOCK su_deinit(); #endif if (arg) su_pthread_port_return_to_parent(arg, -1); return NULL; /* Exit from thread */ }