static void _dispatch_queue(struct harbor *h, struct skynet_context * context, struct msg_queue * queue, uint32_t handle, const char name[GLOBALNAME_LENGTH] ) { int harbor_id = handle >> HANDLE_REMOTE_SHIFT; assert(harbor_id != 0); int fd = h->remote_fd[harbor_id]; if (fd < 0) { char tmp [GLOBALNAME_LENGTH+1]; memcpy(tmp, name , GLOBALNAME_LENGTH); tmp[GLOBALNAME_LENGTH] = '\0'; skynet_error(context, "Drop message to %s (in harbor %d)",tmp,harbor_id); return; } struct msg * m = _pop_queue(queue); while (m) { struct remote_message_header * cookie = (struct remote_message_header *)(m->buffer + m->size - sizeof(*cookie)); cookie->destination |= (handle & HANDLE_MASK); _header_to_message(cookie, (uint32_t *)cookie); int err = _send_package(fd, m->buffer, m->size); if (err) { close(fd); h->remote_fd[harbor_id] = _connect_to(context, h->remote_addr[harbor_id]); if (h->remote_fd[harbor_id] < 0) { skynet_error(context, "Reconnect to harbor %d %s failed",harbor_id, h->remote_addr[harbor_id]); return; } } free(m->buffer); m = _pop_queue(queue); } }
static int _send_remote(int fd, const char * buffer, size_t sz, struct remote_message_header * cookie) { uint32_t sz_header = htonl(sz+sizeof(*cookie)); struct iovec part[3]; part[0].iov_base = &sz_header; part[0].iov_len = 4; part[1].iov_base = (char *)buffer; part[1].iov_len = sz; uint32_t header[3]; _header_to_message(cookie, header); part[2].iov_base = header; part[2].iov_len = sizeof(header); for (;;) { int err = writev(fd, part, 3); if (err < 0) { switch (errno) { case EAGAIN: case EINTR: continue; } } if (err != sz+sizeof(*cookie)+4) { return 1; } return 0; } }
static void _send_remote(struct skynet_context * ctx, int fd, const char * buffer, size_t sz, struct remote_message_header * cookie) { uint32_t sz_header = sz+sizeof(*cookie); uint8_t * sendbuf = (uint8_t *)skynet_malloc(sz_header+4); to_bigendian(sendbuf, sz_header); memcpy(sendbuf+4, buffer, sz); _header_to_message(cookie, sendbuf+4+sz); if (skynet_socket_send(ctx, fd, sendbuf, sz_header+4)) { skynet_error(ctx, "Remote send to %d error", fd); } }
static void _dispatch_queue(struct harbor *h, struct msg_queue * queue, uint32_t handle, const char name[GLOBALNAME_LENGTH] ) { int harbor_id = handle >> HANDLE_REMOTE_SHIFT; assert(harbor_id != 0); struct skynet_context * context = h->ctx; int fd = h->remote_fd[harbor_id]; if (fd < 0) { char tmp [GLOBALNAME_LENGTH+1]; memcpy(tmp, name , GLOBALNAME_LENGTH); tmp[GLOBALNAME_LENGTH] = '\0'; skynet_error(context, "Drop message to %s (in harbor %d)",tmp,harbor_id); return; } struct msg * m = _pop_queue(queue); while (m) { struct remote_message_header cookie; uint8_t *ptr = m->buffer + m->size - sizeof(cookie); memcpy(&cookie, ptr, sizeof(cookie)); cookie.destination |= (handle & HANDLE_MASK); _header_to_message(&cookie, ptr); _send_package(context, fd, m->buffer, m->size); m = _pop_queue(queue); } }