/** * Allocates space for a new socket structure * @return Pointer to the allocated structure or NULL on failure */ comms_socket_t *comms_sock_new(void) { comms_socket_t *sock; sock = (comms_socket_t *) calloc(1, sizeof(struct comms_socket)); if (!sock) return NULL; log_enter(); sock->can_read = false; sock->can_write = false; sock->have_exception = false; sock->poll_handle = NULL; sock->state = NETSOCK_STATE_NONE; sock->fd = INVALID_SOCK; sock->last_errno = -1; sock->is_socket = true; sock->in_buffer = netbuf_new(1, 4 * 1024 * 1024); if (!sock->in_buffer) { BLAST_SAFE_FREE(sock); blast_err("Could not allocate in_buffer"); return NULL; } sock->out_buffer = netbuf_new(1, 1024 * 1024); if (!sock->out_buffer) { netbuf_free(sock->in_buffer); BLAST_SAFE_FREE(sock); log_leave("Could not allocate out_buffer"); return NULL; } log_leave(); return sock; }
/** * Retrieves the address info structure for the given hostname:port combination. This assumes a TCP/IP * connection * @param m_hostname Destination hostname in either DNS or xx.xx.xx.xx format * @param m_port Port number for the service * @param m_udp True if the port is a UDP port * @param m_ai Double pointer that will be allocated by by getaddrinfo() * @return return code from getaddrinfo */ static int comms_sock_get_addrinfo(const char *m_hostname, uint32_t m_port, bool m_udp, struct addrinfo **m_ai) { char *service = NULL; struct addrinfo request = { 0 }; int retval = 0; log_enter(); if (!m_udp) { request.ai_protocol = IPPROTO_TCP; request.ai_socktype = SOCK_STREAM; } else { request.ai_protocol = IPPROTO_UDP; request.ai_socktype = SOCK_DGRAM; } request.ai_family = PF_UNSPEC; request.ai_flags = AI_PASSIVE; if (m_port) { blast_tmp_sprintf(service, "%hu", m_port); request.ai_flags = AI_NUMERICSERV; } retval = getaddrinfo(m_hostname, service, &request, m_ai); log_leave(); return retval; }
void *thread_func_aew(void *arg) { struct env_aew *env = arg; void *status = THREAD_SUCCESS; struct image_buffer_description *image = NULL; log_enter(); log_dbg("meet\n"); Rendezvous_meet(env->rendezvous_init); while (!gblGetQuit()) { usleep(10000); if (fifo_get(env->fifo_aew, &image) == FIFO_FAILURE) { breakLoop(THREAD_FAILURE); } if (image == NULL) { //阻塞FIFO,只有FIFO中有消息才会执行下去 breakLoop(THREAD_SUCCESS); } capture_buffer_put(image); } Rendezvous_force(env->rendezvous_init); Rendezvous_meet(env->rendezvous_deinit); log("exit aew thread\n"); log_exit(); return status; }
/** * Sets up a multicast listening port. * @param m_sock Allocated socket * @param m_hostname Should be "224.0.0.x" where x is between 0 and 255 * @param m_port Multicast port number * @return NETSOCK_OK on success, NETSOCK_ERR on failure */ int comms_sock_multicast_listen(comms_socket_t *m_sock, const char *m_hostname, uint32_t m_port) { socket_t fd; in_addr_t group; int loop = 0; log_enter(); if (!m_sock || m_sock->state != NETSOCK_STATE_NONE) return NETSOCK_ERR; fd = comms_sock_bind("0.0.0.0", m_port, true); if (fd == INVALID_SOCK) return NETSOCK_ERR; comms_sock_set_fd(m_sock, fd); if ((group = inet_addr(m_hostname)) == INADDR_NONE) return NETSOCK_ERR; if (comms_sock_join_mcast(m_sock, group) == NETSOCK_ERR) return NETSOCK_ERR; setsockopt(m_sock->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); BLAST_SAFE_FREE(m_sock->host); m_sock->addr.sin_family = AF_INET; m_sock->addr.sin_addr.s_addr = group; m_sock->addr.sin_port = htons(m_port); m_sock->addrlen = sizeof(m_sock->addr); m_sock->host = strdup(m_hostname); m_sock->port = m_port; m_sock->udp = 1; m_sock->state = NETSOCK_STATE_CONNECTING; comms_net_async_set_events(comms_sock_get_poll_handle(m_sock), POLLOUT); log_leave(); return NETSOCK_OK; }
/** * Connects an allocated socket to a given remote host:port combination * @param m_hostname * @param m_port * @return */ static socket_t comms_sock_connect_fd(const char *m_hostname, uint32_t m_port, bool m_udp) { socket_t sock = -1; int retval; struct addrinfo *addrinfo_group; struct addrinfo *ai; log_enter(); retval = comms_sock_get_addrinfo(m_hostname, m_port, m_udp, &addrinfo_group); if (retval != 0) { blast_err("Failed to resolve hostname %s (%s)", m_hostname, gai_strerror(retval)); log_leave(); return NETSOCK_ERR; } for (ai = addrinfo_group; ai != NULL; ai = ai->ai_next) { /* create socket */ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock < 0) { blast_err("Socket create failed: %s", strerror(errno)); continue; } fcntl(sock, F_SETFL, O_NONBLOCK); if (!m_udp) connect(sock, ai->ai_addr, ai->ai_addrlen); break; } freeaddrinfo(addrinfo_group); log_leave(); return sock; }
static int comms_sock_raw_read(comms_socket_t *m_sock, void *m_buf, size_t m_len) { int retval = NETSOCK_ERR; log_enter(); if (m_sock->have_exception) { log_leave(); return NETSOCK_ERR; } if (m_sock->is_socket) { m_sock->addrlen = sizeof(m_sock->addr); retval = recvfrom(m_sock->fd, m_buf, m_len, 0, &m_sock->addr, &m_sock->addrlen); } else { retval = read(m_sock->fd, m_buf, m_len); } m_sock->last_errno = errno; m_sock->can_read = false; if (retval < 0) { m_sock->have_exception = true; } log_leave(); return retval; }
static int comms_sock_raw_write(comms_socket_t *m_sock, const void *m_buf, size_t m_len) { ssize_t retval = NETSOCK_ERR; log_enter(); if (m_sock->have_exception) { log_leave(); return NETSOCK_ERR; } if (m_sock->is_socket) { if (m_sock->udp) { retval = sendto(m_sock->fd, m_buf, m_len, m_sock->flags, &m_sock->addr, m_sock->addrlen); } else { /// Cap the maximum we send at any given point to the default segment size for TCP m_len = min(m_len, DEFAULT_MTU); retval = send(m_sock->fd, m_buf, m_len, m_sock->flags); } } else { retval = write(m_sock->fd, m_buf, m_len); } m_sock->last_errno = errno; if (m_sock->poll_handle) { comms_net_async_add_events(m_sock->poll_handle, POLLOUT); } if (retval < 0) { m_sock->have_exception = true; } log_leave(); return retval; }
comms_net_async_handle_t *comms_sock_get_poll_handle(comms_socket_t *m_sock) { log_enter(); if (!m_sock->poll_handle) { m_sock->poll_handle = comms_net_async_handler_new(m_sock->fd, 0, comms_sock_poll, m_sock); }log_leave(); return m_sock->poll_handle; }
void comms_sock_set_fd(comms_socket_t *m_sock, socket_t m_fd) { log_enter(); m_sock->fd = m_fd; if (m_sock->poll_handle) { comms_net_async_set_sock(m_sock->poll_handle, m_fd); } log_leave(); }
/* * Set the fields in the 'target' clone to the specified values. * Then, look at all clones to determine which message types are * currently active and which clone is the primary console queue. * If the primary console queue changes to or from the backlog * queue, copy all messages from backlog to primary or vice versa. */ void log_update(log_t *target, queue_t *q, short flags, log_filter_t *filter) { log_t *lp; short active = SL_CONSOLE; zone_t *zptr = NULL; log_zone_t *lzp; zoneid_t zoneid = target->log_zoneid; int i; log_enter(); if (q != NULL) target->log_q = q; target->log_wanted = filter; target->log_flags = flags; target->log_overflow = 0; /* * Need to special case the global zone here since this may be * called before zone_init. */ if (zoneid == GLOBAL_ZONEID) { lzp = &log_global; } else if ((zptr = zone_find_by_id(zoneid)) == NULL) { log_exit(); return; /* zone is being destroyed, ignore update */ } else { lzp = zone_getspecific(log_zone_key, zptr); } ASSERT(lzp != NULL); for (i = LOG_LOGMAXIDX; i >= LOG_LOGMINIDX; i--) { lp = &lzp->lz_clones[i]; if (zoneid == GLOBAL_ZONEID && (lp->log_flags & SL_CONSOLE)) log_consq = lp->log_q; active |= lp->log_flags; } lzp->lz_active = active; if (zptr) zone_rele(zptr); if (log_consq == target->log_q) { if (flags & SL_CONSOLE) log_conswitch(&log_backlog, target); else log_conswitch(target, &log_backlog); } target->log_q = q; log_exit(); }
int comms_sock_flush(comms_socket_t *m_sock) { uint32_t len; int retval; log_enter(); if (!comms_sock_is_open(m_sock)) { blast_err("Could not write to closed socket %s", m_sock->host ? m_sock->host : "(Unknown host)"); log_leave(); return NETSOCK_ERR; } len = netbuf_bytes_available(m_sock->out_buffer); if (m_sock->poll_handle && len > 0) { if (!__sync_lock_test_and_set(&m_sock->can_write, false)) { comms_net_async_add_events(m_sock->poll_handle, POLLOUT); log_leave(); return NETSOCK_AGAIN; } void *data; len = netbuf_peek(m_sock->out_buffer, &data); if (len) { retval = comms_sock_raw_write(m_sock, data, len); free(data); if (retval < 0) { comms_sock_close(m_sock); blast_err("Could not write socket: %s", strerror(m_sock->last_errno)); log_leave(); return NETSOCK_ERR; } netbuf_eat(m_sock->out_buffer, retval); } } /** * If we have data left to write to the socket, then we force the POLLOUT event to allow * our async handler to catch and process the data in the next poll call. */ len = netbuf_bytes_available(m_sock->out_buffer); if (m_sock->poll_handle && len > 0) { comms_net_async_add_events(m_sock->poll_handle, POLLOUT); log_leave(); return NETSOCK_AGAIN; } log_leave(); return NETSOCK_OK; }
void comms_sock_close(comms_socket_t *m_sock) { log_enter(); if (comms_sock_is_open(m_sock)) { if (close(m_sock->fd) == -1) m_sock->last_errno = errno; m_sock->fd = INVALID_SOCK; m_sock->state = NETSOCK_STATE_CLOSED; } if (m_sock->poll_handle) { comms_net_async_handler_free(m_sock->poll_handle); m_sock->poll_handle = NULL; }log_leave("Closed"); }
/** * Binds a socket structure to a specific host:port combination. * @param m_hostname * @param m_port Port number to connect * @param m_udp If false, build a stream-based tcp connection * @return */ static socket_t comms_sock_bind(const char *m_hostname, uint32_t m_port, bool m_udp) { socket_t sock = -1; int retval; struct addrinfo *addrinfo_group; struct addrinfo *ai; int sock_opt = 1; log_enter(); retval = comms_sock_get_addrinfo(m_hostname, m_port, m_udp, &addrinfo_group); if (retval != 0) { blast_err("Failed to resolve hostname %s (%s)", m_hostname, gai_strerror(retval)); log_leave(); return NETSOCK_ERR; } for (ai = addrinfo_group; ai != NULL; ai = ai->ai_next) { /* create socket */ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock < 0) { blast_err("Socket create failed: %s", strerror(errno)); continue; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sock_opt, sizeof(sock_opt)) < 0) { freeaddrinfo(addrinfo_group); close(sock); log_leave(); blast_err("Couldn't reuse socket for port %d", m_port); return NETSOCK_ERR; } if (bind(sock, ai->ai_addr, ai->ai_addrlen)) { freeaddrinfo(addrinfo_group); close(sock); log_leave(); blast_err("Couldn't bind to socket for port %d", m_port); return NETSOCK_ERR; } break; } freeaddrinfo(addrinfo_group); log_leave(); return sock; }
void comms_sock_free(comms_socket_t *m_sock) { log_enter(); if (!m_sock) { log_leave("No socket"); return; } comms_sock_close(m_sock); netbuf_free(m_sock->in_buffer); netbuf_free(m_sock->out_buffer); BLAST_SAFE_FREE(m_sock->host); BLAST_SAFE_FREE(m_sock); log_leave("Freed"); }
static int comms_sock_connect_generic(comms_socket_t *m_sock, const char *m_hostname, uint32_t m_port, bool m_udp) { socket_t fd; log_enter(); if (!m_sock || m_sock->state != NETSOCK_STATE_NONE) return NETSOCK_ERR; fd = comms_sock_connect_fd(m_hostname, m_port, m_udp); if (fd == INVALID_SOCK) return NETSOCK_ERR; comms_sock_set_fd(m_sock, fd); BLAST_SAFE_FREE(m_sock->host); m_sock->host = strdup(m_hostname); m_sock->port = m_port; m_sock->udp = m_udp; m_sock->state = NETSOCK_STATE_CONNECTING; comms_net_async_set_events(comms_sock_get_poll_handle(m_sock), POLLOUT); log_leave(); return NETSOCK_OK; }
/** * Takes a double-pointer to a socket and ensures that it is in a pristine state, ready for a new connection. * @param m_sock Double pointer to a socket */ void comms_sock_reset(comms_socket_t **m_sock) { log_enter(); if (!(*m_sock)) { *m_sock = comms_sock_new(); return; } comms_sock_close(*m_sock); (*m_sock)->fd = INVALID_SOCK; (*m_sock)->last_errno = -1; (*m_sock)->is_socket = true; netbuf_reinit((*m_sock)->in_buffer); netbuf_reinit((*m_sock)->out_buffer); (*m_sock)->can_read = false; (*m_sock)->can_write = false; (*m_sock)->have_exception = false; BLAST_ZERO((*m_sock)->callbacks); (*m_sock)->poll_handle = comms_sock_get_poll_handle(*m_sock); (*m_sock)->state = NETSOCK_STATE_NONE; (*m_sock)->flags = 0; log_leave(); }
void log_sendmsg(mblk_t *mp, zoneid_t zoneid) { log_t *lp; char *src, *dst; mblk_t *mp2 = mp->b_cont; log_ctl_t *lc = (log_ctl_t *)mp->b_rptr; int flags, fac; off_t facility = 0; off_t body = 0; zone_t *zptr = NULL; log_zone_t *lzp; int i; int backlog; /* * Need to special case the global zone here since this may be * called before zone_init. */ if (zoneid == GLOBAL_ZONEID) { lzp = &log_global; } else if ((zptr = zone_find_by_id(zoneid)) == NULL) { /* specified zone doesn't exist, free message and return */ log_freemsg(mp); return; } else { lzp = zone_getspecific(log_zone_key, zptr); } ASSERT(lzp != NULL); if ((lc->flags & lzp->lz_active) == 0) { if (zptr) zone_rele(zptr); log_freemsg(mp); return; } if (panicstr) { /* * Raise the console queue's q_hiwat to ensure that we * capture all panic messages. */ log_consq->q_hiwat = 2 * LOG_HIWAT; log_consq->q_flag &= ~QFULL; /* Message was created while panicking. */ lc->flags |= SL_PANICMSG; } src = (char *)mp2->b_rptr; dst = strstr(src, "FACILITY_AND_PRIORITY] "); if (dst != NULL) { facility = dst - src; body = facility + 23; /* strlen("FACILITY_AND_PRIORITY] ") */ } log_enter(); /* * In the early boot phase hrestime is invalid, then timechanged is 0. * If hrestime is not valid, the ttime is set to 0 here and the correct * ttime is calculated in log_conswitch() later. The log_conswitch() * calculation to determine the correct ttime does not use ttime data * from these log_ctl_t structures; it only uses ttime from log_ctl_t's * that contain good data. * */ lc->ltime = ddi_get_lbolt(); if (timechanged) { lc->ttime = gethrestime_sec(); } else { lc->ttime = 0; } flags = lc->flags & lzp->lz_active; log_seq_no[flags & SL_ERROR]++; log_seq_no[flags & SL_TRACE]++; log_seq_no[flags & SL_CONSOLE]++; /* * If this is in the global zone, start with the backlog, then * walk through the clone logs. If not, just do the clone logs. */ backlog = (zoneid == GLOBAL_ZONEID); i = LOG_LOGMINIDX; while (i <= LOG_LOGMAXIDX) { if (backlog) { /* * Do the backlog this time, then start on the * others. */ backlog = 0; lp = &log_backlog; } else { lp = &lzp->lz_clones[i++]; } if ((lp->log_flags & flags) && lp->log_wanted(lp, lc)) { if (canput(lp->log_q)) { lp->log_overflow = 0; lc->seq_no = log_seq_no[lp->log_flags]; if ((mp2 = copymsg(mp)) == NULL) break; if (facility != 0) { src = (char *)mp2->b_cont->b_rptr; dst = src + facility; fac = (lc->pri & LOG_FACMASK) >> 3; dst += snprintf(dst, LOG_FACSIZE + LOG_PRISIZE, "%s.%s", log_fac[MIN(fac, LOG_NFACILITIES)], log_pri[lc->pri & LOG_PRIMASK]); src += body - 2; /* copy "] " too */ while (*src != '\0') *dst++ = *src++; *dst++ = '\0'; mp2->b_cont->b_wptr = (uchar_t *)dst; } (void) putq(lp->log_q, mp2); } else if (++lp->log_overflow == 1) {
/** * Main routine providing callback handling for asynchronous socket connections. * @param m_handle Pointer to the asynchronous handler * @param m_fd File descriptor for the network socket * @param m_events Received events flags * @param m_sock Pointer to the comms_socket structure * @return NETSOCK_OK on success, NETSOCK_ERR on failure */ static int comms_sock_poll(comms_net_async_handle_t *m_handle, socket_t m_fd, uint16_t m_events, void *m_sock) { comms_socket_t *sock = (comms_socket_t*) m_sock; char buffer[COMMS_NETSOCK_BUF_SIZE]; int retval = 0; socklen_t errlen = sizeof(sock->last_errno); log_enter(); if (!comms_sock_is_open(sock)) { log_leave(); return NETSOCK_ERR; } if (m_events & POLLERR) { /** * If we catch an error while connecting, we use getsockopt to try and determine the cause of the error. * The connected callback in then fired with NETSOCK_ERR */ if (sock->state == NETSOCK_STATE_CONNECTING) { sock->state = NETSOCK_STATE_ERROR; blast_err("Got error while connecting to %s", sock->host); if (sock->is_socket) getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (void *) &sock->last_errno, &errlen); comms_sock_close(sock); if (sock->callbacks.connected) { sock->callbacks.connected(NETSOCK_ERR, sock->last_errno, sock->callbacks.priv); }log_leave(); return NETSOCK_ERR; } /** * If we catch an error and we are not trying to connect, then we fall through to the POLLIN handler to * process the error */ comms_net_async_del_events(m_handle, POLLERR); m_events |= POLLIN; } if (m_events & (POLLIN | POLLPRI)) { sock->can_read = true; retval = comms_sock_raw_read(sock, buffer, sizeof(buffer)); /** * Caught an error. Likely broken pipe. Errno is stored in the sock struct. */ if (retval < 0) { retval = -1; if (m_handle) { comms_net_async_del_events(m_handle, POLLIN | POLLERR); } if (sock->callbacks.error) { sock->callbacks.error(sock->last_errno, sock->callbacks.priv); } } /** * No more data are available. This is the EOF condition */ if (retval == 0) { comms_net_async_del_events(m_handle, POLLIN); m_events |= POLLHUP; } /** * Got actual data. Buffer it and pass on to the user callback function */ if (retval > 0) { size_t written = netbuf_write(sock->in_buffer, buffer, retval); size_t to_write = retval - written; if (sock->callbacks.data) { void *data; size_t len = netbuf_peek(sock->in_buffer, &data); if (len) { retval = sock->callbacks.data(data, len, sock->callbacks.priv); if (retval > 0) netbuf_eat(sock->in_buffer, retval); if (netbuf_bytes_available(sock->in_buffer)) comms_net_async_add_events(m_handle, POLLIN); free(data); } } /// If we didn't get everything in, try one more time if (to_write) { if (netbuf_write(sock->in_buffer, buffer + written, to_write)) blast_warn( "Discarding data due to overfull in_buffer on %s", sock->host ? sock->host : "(NULL)"); } } } if (m_events & POLLHUP) { if (sock->callbacks.finished) { void *data; size_t len = netbuf_peek(sock->in_buffer, &data); if (len) { sock->callbacks.finished(data, len, sock->callbacks.priv); if (sock->in_buffer) netbuf_eat(sock->in_buffer, len); free(data); } sock->state = NETSOCK_STATE_CLOSED; }log_leave(); return NETSOCK_OK; } if (m_events & POLLOUT) { if (sock->state == NETSOCK_STATE_CONNECTING) { sock->state = NETSOCK_STATE_CONNECTED; comms_net_async_set_events(m_handle, POLLPRI | POLLIN | POLLOUT); fcntl(sock->fd, F_SETFL, 0); if (sock->callbacks.connected) { sock->callbacks.connected(NETSOCK_OK, 0, sock->callbacks.priv); } log_leave(); return NETSOCK_OK; } sock->can_write = true; comms_net_async_del_events(m_handle, POLLOUT); if (netbuf_bytes_available(sock->out_buffer)) { comms_sock_flush(sock); } else if (sock->callbacks.control) { sock->callbacks.control(NETSOCK_WRITABLE, sock->callbacks.priv); } } log_leave(); return retval; }