/* This is for register side. */ static void register_thread_listen( int* tcp, int* exit_time) { /*******/ /* TCP */ /*******/ struct sockaddr_in server_addr; int on = 1; if ((*tcp = socket(AF_INET, SOCK_STREAM, 0)) < 0) { /* perror("Socket");*/ return; } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(NL_REGISTER_PORT); server_addr.sin_addr.s_addr = INADDR_ANY; memset(&(server_addr.sin_zero), 0, 8); // Re-use socket if you can. setsockopt(tcp, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if(bind(*tcp, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) < 0) { LOG("Unable to bind. Make sure no other instance of register is running."); return; } if(listen(*tcp, 5) < 0) { /*perror("Listen");*/ return; } do { socklen_t sin_size = sizeof(struct sockaddr_in); struct sockaddr_in s; long int socket = accept(*tcp, (struct sockaddr*)&s, &sin_size); char buffer[NL_BUFFER_SIZE+1]; LOG("I got a connection from (%s, %d)", inet_ntoa(s.sin_addr), ntohs(s.sin_port)); if(!nl_tcp_rcv(buffer, socket)) break; if(buffer[0] == 'C') /* A clients wants to know who already registered. */ { client* c = (client*)mmalloc(sizeof(client)); int port; /* Client's UDP port */ c->socket = socket; #warning Check for errors. sscanf(buffer + 2, "%d", &port); /* Client's UDP port */ /* * TODO: Shall we have a limit of peer that can connect? * Let's say, 2000? */ /* This should be the UDP port we can connect on. */ s.sin_port = htons(port); c->addr = s; LOG("Client's UDP port: %d.", port); lock_init(c); thread_detached(c->t, tcp_register_client_thread, (void*)c); } else if(buffer[0] == 'S') /* A server wants to register. */ { char* remember; server_game* g = (server_game*)mmalloc(sizeof(server_game)); /* * Packet format: * * port internal_address name */ #warning Check for errors. int port; sscanf(_strtok_r(buffer + 2, " ", &remember), "%d", &port); /* Server's TCP port */ char* internal_ip = _strtok_r(NULL, " ", &remember); char* name = _strtok_r(NULL, "\n", &remember); /* Server's name */ g->socket = socket; /* This should be the TCP port we can connect on. */ s.sin_port = htons(port); /* * First: Check if we can connect to this address from * outside. If not, there's no need to continue: * nobody will be able to connect to it! */ if(!nl_test_connection(s)) { LOG("Some server tried to connect, but I " "cannot reach it from the other side.\nAborting."); nl_tcp_snd("I", socket); /* Impossible to connect. */ mfree(g); continue; } /* Here, we check if the provided server name already exists * in the server list. If so, return Nack. */ if(rGetByKey(&game_server_array, buffer, NULL) != NULL) { LOG("Game server with the same exists. Aborting."); nl_tcp_snd("N", socket); mfree(g); continue; } nl_tcp_snd("O", socket); /* It's okay. */ LOG("Success: Server with TCP port %d added.", port); g->name = m_strdup(name); g->addr = s; g->internal_ip = m_strdup(internal_ip); lock_init(g); thread_detached(g->t, tcp_register_server_thread, (void*)g); } else if(buffer[0] == 'N') /* N is used when trying to quit. */ { LOG("Exit message."); } } while(!(*exit_time)); close(*tcp); LOG("Socket closed."); }
/* open the text dict */ static xdict_t _xdict_open_txt(const char *fpath, int mode, unsigned char *ml) { xdict_t xd; xtree_t xt; char buf[XDICT_PATH_MAX], tmpfile[XDICT_PATH_MAX]; struct stat st1, st2; // check the input filepath _realpath(fpath, buf); if (stat(buf, &st1) < 0) return NULL; // check dest file & orginal file, compare there mtime #ifdef WIN32 { char *tmp_ptr; GetTempPath(sizeof(tmpfile) - 20, tmpfile); tmp_ptr = tmpfile + strlen(tmpfile); if (tmp_ptr[-1] == '\\') tmp_ptr--; sprintf(tmp_ptr, "\\scws-%08x.xdb", scws_crc32(buf)); } #else sprintf(tmpfile, "/tmp/scws-%08x.xdb", scws_crc32(buf)); #endif if (!stat(tmpfile, &st2) && st2.st_mtime > st1.st_mtime) { xdb_t x; if ((x = xdb_open(tmpfile, 'r')) != NULL) { xd = (xdict_t) malloc(sizeof(xdict_st)); memset(xd, 0, sizeof(xdict_st)); xd->ref = 1; if (mode & SCWS_XDICT_MEM) { /* convert the xdb(disk) -> xtree(memory) */ if ((xt = xdb_to_xtree(x, NULL)) != NULL) { xdb_close(x); xd->xdict = (void *) xt; xd->xmode = SCWS_XDICT_MEM; return xd; } } xd->xmode = SCWS_XDICT_XDB; xd->xdict = (void *) x; return xd; } } // create xtree if ((xt = xtree_new(0, 0)) == NULL) return NULL; else { int cl, kl; FILE *fp; word_st word, *w; char *key, *part, *last, *delim = " \t\r\n"; // re-build the xdb file from text file if ((fp = fopen(buf, "r")) == NULL) return NULL; // parse every line word.attr[2] = '\0'; while (fgets(buf, sizeof(buf) - 1, fp) != NULL) { // <word>[\t<tf>[\t<idf>[\t<attr>]]] if (buf[0] == ';' || buf[0] == '#') continue; key = _strtok_r(buf, delim, &last); if (key == NULL) continue; kl = strlen(key); // init the word do { word.tf = word.idf = 1.0; word.flag = SCWS_WORD_FULL; word.attr[0] = '@'; word.attr[1] = '\0'; if (!(part = _strtok_r(NULL, delim, &last))) break; word.tf = (float) atof(part); if (!(part = _strtok_r(NULL, delim, &last))) break; word.idf = (float) atof(part); if ((part = _strtok_r(NULL, delim, &last))) { word.attr[0] = part[0]; if (part[1]) word.attr[1] = part[1]; } } while (0); // save into xtree if ((w = xtree_nget(xt, key, kl, NULL)) == NULL) { w = (word_st *) pmalloc(xt->p, sizeof(word_st)); memcpy(w, &word, sizeof(word)); xtree_nput(xt, w, sizeof(word), key, kl); } else { w->tf = word.tf; w->idf = word.idf; w->flag |= word.flag; strcpy(w->attr, word.attr); } // parse the part cl = ml[(unsigned char) (key[0])]; while (1) { cl += ml[(unsigned char) (key[cl])]; if (cl >= kl) break; if ((w = xtree_nget(xt, key, cl, NULL)) != NULL) w->flag |= SCWS_WORD_PART; else { w = (word_st *) pmalloc_z(xt->p, sizeof(word_st)); w->flag = SCWS_WORD_PART; xtree_nput(xt, w, sizeof(word), key, cl); } } } fclose(fp); // optimize the xtree & save to xdb xtree_optimize(xt); unlink(tmpfile); xtree_to_xdb(xt, tmpfile); chmod(tmpfile, 0777); // return xtree xd = (xdict_t) malloc(sizeof(xdict_st)); memset(xd, 0, sizeof(xdict_st)); xd->ref = 1; xd->xdict = (void *) xt; xd->xmode = SCWS_XDICT_MEM; return xd; } }