static int _remote_send_handle(struct harbor *h, struct skynet_context * context, uint32_t source, uint32_t destination, int type, int session, const char * msg, size_t sz) { int harbor_id = destination >> HANDLE_REMOTE_SHIFT; assert(harbor_id != 0); if (harbor_id == h->id) { // local message skynet_send(context, source, destination , type | PTYPE_TAG_DONTCOPY, session, (void *)msg, sz); return 1; } int fd = h->remote_fd[harbor_id]; if (fd >= 0) { struct remote_message_header cookie; cookie.source = source; cookie.destination = (destination & HANDLE_MASK) | ((uint32_t)type << HANDLE_REMOTE_SHIFT); cookie.session = (uint32_t)session; int err = _send_remote(fd, msg,sz,&cookie); 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 0; } } } else { _request_master(h, context, NULL, 0, harbor_id); skynet_error(context, "Drop message to harbor %d from %x to %x (session = %d, msgsz = %d)",harbor_id, source, destination,session,(int)sz); } return 0; }
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); } }
HARBOR_API int harbor_init(struct harbor *h, struct skynet_context *ctx, const char * args) { h->ctx = ctx; int sz = strlen(args)+1; //char master_addr[sz]; //char local_addr[sz]; char master_addr[100]; char local_addr[100]; int harbor_id = 0; sscanf(args,"%s %s %d",master_addr, local_addr, &harbor_id); h->master_addr = skynet_strdup(master_addr); h->id = harbor_id; h->master_fd = _connect_to(h, master_addr, true); if (h->master_fd == -1) { fprintf(stderr, "Harbor: Connect to master failed\n"); exit(1); } h->local_addr = skynet_strdup(local_addr); _launch_gate(ctx, local_addr); skynet_callback(ctx, h, _mainloop); _request_master(h, local_addr, strlen(local_addr), harbor_id); return 0; }
static void _update_address(struct skynet_context * context, struct master *m, int harbor_id, const char * buffer, size_t sz) { if (m->remote_fd[harbor_id] >= 0) { close(m->remote_fd[harbor_id]); m->remote_fd[harbor_id] = -1; } free(m->remote_addr[harbor_id]); char * addr = malloc(sz+1); memcpy(addr, buffer, sz); addr[sz] = '\0'; m->remote_addr[harbor_id] = addr; int fd = _connect_to(addr); if (fd<0) { skynet_error(context, "Can't connect to harbor %d : %s", harbor_id, addr); return; } m->remote_fd[harbor_id] = fd; _broadcast(context, m, addr, sz, harbor_id); int i; for (i=1;i<REMOTE_MAX;i++) { if (i == harbor_id) continue; const char * addr = m->remote_addr[i]; if (addr == NULL) { continue; } _send_to(fd, addr, strlen(addr), i); } }
static void _update_address(struct master *m, int harbor_id, const char * buffer, size_t sz) { if (m->remote_fd[harbor_id] >= 0) { close_harbor(m, harbor_id); } skynet_free(m->remote_addr[harbor_id]); char * addr = (char*)skynet_malloc(sz+1); memcpy(addr, buffer, sz); addr[sz] = '\0'; m->remote_addr[harbor_id] = addr; _connect_to(m, harbor_id); }
static void _update_remote_address(struct harbor *h, int harbor_id, const char * ipaddr) { if (harbor_id == h->id) { return; } assert(harbor_id > 0 && harbor_id< REMOTE_MAX); struct skynet_context * context = h->ctx; if (h->remote_fd[harbor_id] >=0) { skynet_socket_close(context, h->remote_fd[harbor_id]); skynet_free(h->remote_addr[harbor_id]); h->remote_addr[harbor_id] = NULL; } h->remote_fd[harbor_id] = _connect_to(h, ipaddr, false); h->connected[harbor_id] = false; }
static void _update_remote_address(struct skynet_context * context, struct harbor *h, int harbor_id, const char * ipaddr) { if (harbor_id == h->id) { return; } assert(harbor_id > 0 && harbor_id< REMOTE_MAX); if (h->remote_fd[harbor_id] >=0) { close(h->remote_fd[harbor_id]); free(h->remote_addr[harbor_id]); h->remote_addr[harbor_id] = NULL; } h->remote_fd[harbor_id] = _connect_to(context, ipaddr); if (h->remote_fd[harbor_id] >= 0) { free(h->remote_addr[harbor_id]); h->remote_addr[harbor_id] = strdup(ipaddr); } }
static void _request_master(struct harbor *h, struct skynet_context * context, const char name[GLOBALNAME_LENGTH], size_t i, uint32_t handle) { char buffer[4+i]; handle = htonl(handle); memcpy(buffer, &handle, 4); memcpy(buffer+4,name,i); int err = _send_package(h->master_fd, buffer, 4+i); if (err) { close(h->master_fd); h->master_fd = _connect_to(context, h->master_addr); if (h->master_fd < 0) { skynet_error(context, "Reconnect to master server %s failed", h->master_addr); return; } _send_package(h->master_fd, buffer, 4+i); } }
int harbor_init(struct harbor *h, struct skynet_context *ctx, const char * args) { int sz = strlen(args)+1; char master_addr[sz]; char local_addr[sz]; int harbor_id = 0; sscanf(args,"%s %s %d",master_addr, local_addr, &harbor_id); int master_fd = _connect_to(ctx, master_addr); if (master_fd < 0) { skynet_error(ctx, "Harbor : Connect to master %s faild",master_addr); return 1; } printf("Connect to master %s\n",master_addr); h->master_addr = strdup(master_addr); h->master_fd = master_fd; char tmp[128]; sprintf(tmp,"gate L ! %s %d %d 0",local_addr, PTYPE_HARBOR, REMOTE_MAX); const char * gate_addr = skynet_command(ctx, "LAUNCH", tmp); if (gate_addr == NULL) { skynet_error(ctx, "Harbor : launch gate failed"); return 1; } uint32_t gate = strtoul(gate_addr+1 , NULL, 16); if (gate == 0) { skynet_error(ctx, "Harbor : launch gate invalid %s", gate_addr); return 1; } const char * self_addr = skynet_command(ctx, "REG", NULL); int n = sprintf(tmp,"broker %s",self_addr); skynet_send(ctx, 0, gate, PTYPE_TEXT, 0, tmp, n); skynet_send(ctx, 0, gate, PTYPE_TEXT, 0, "start", 5); h->id = harbor_id; skynet_callback(ctx, h, _mainloop); _report_local_address(h, ctx, local_addr, harbor_id); return 0; }
static void _broadcast(struct skynet_context * context, struct master *m, const char *name, size_t sz, uint32_t handle) { int i; for (i=1;i<REMOTE_MAX;i++) { int fd = m->remote_fd[i]; if (fd < 0) continue; int err = _send_to(fd, name, sz, handle); if (err) { close(fd); fd = _connect_to(m->remote_addr[i]); if (fd < 0) { m->remote_fd[i] = -1; skynet_error(context, "Reconnect to harbor %d : %s faild", i, m->remote_addr[i]); } else { if (_send_to(fd, name, sz, handle)) { close(fd); m->remote_fd[i] = -1; } } } } }