/** * NAME: ident_put * PURPOSE: add string to the hash table * ARGS: str - string to add * len - string length * RETURN: identifier number of the added string * NOTE: str might be not \0 terminated */ ident_t ident_put(char const *str, int len) { hash_t hash; hash_t index; char *str_dup; if (!ident_state.initialized) ident_init(); assert(len >= 0); ident_state.stat_lookups_num++; if (len == 0) { ident_state.stat_success_num++; return ident_empty; } hash = ident_hash(str, len); index = hash % ident_state.table_size; ident_state.stat_cycles_num++; while (ident_state.table[index].hash != 0) { if (ident_state.table[index].hash == hash && ident_state.table[index].len == len) { if (!strncmp(str, ident_state.table[index].string, len)) { ident_state.stat_success_num++; return ident_state.table[index].ident; } } index = (index + HASH_STEP) % ident_state.table_size; ident_state.stat_cycles_num++; } /* make the duplicate of the string */ str_dup = (char*) xmalloc(len + 1); memcpy(str_dup, str, len); str_dup[len] = 0; /* Not found in the table */ if (ident_state.total_idents >= ident_state.rehash_size) { ident_rehash(); /* The old calculated index is invalid, so we should make new one */ ident_state.map[ident_state.total_idents] = ident_do_put(hash, str_dup, ident_state.total_idents, len); } else { /* Use already calculated slot */ ident_state.map[ident_state.total_idents] = index; ident_state.table[index].hash = hash; ident_state.table[index].string = str_dup; ident_state.table[index].ident = ident_state.total_idents; ident_state.table[index].len = len; } return ident_state.total_idents++; }
/** * NAME: ident_get * PURPOSE: get string by the identifier number * ARGS: id - identifier number * RETURN: string in the hash table (MUST NOT BE ALTERED) */ char * ident_get(ident_t id) { if (!ident_state.initialized) ident_init(); assert(/*id >= 0 && */id < (ident_t) ident_state.total_idents); return ident_state.table[ident_state.map[id]].string; }
int main(int argc, char **argv) { /* parse options */ int errflg = 0; extern char *optarg; extern int optind, optopt; int c; while ((c = getopt(argc, argv, "a:P:C:p:f:R:n:")) != -1) { switch(c) { case 'a': strncpy(mcast_dotted, optarg, sizeof(mcast_dotted) - 1); if (strlen(mcast_dotted) == 0) errflg++; break; case 'P': data_port = (in_port_t) atoi(optarg); break; case 'C': ctrl_port = (in_port_t) atoi(optarg); break; case 'p': psize = atoi(optarg); if (psize <= 0 || psize > (int) PROTO_MAX_DATA) errflg++; break; case 'f': fsize = atoi(optarg); if (fsize <= 0) errflg++; break; case 'R': rtime = atoi(optarg); if (rtime <= 0) errflg++; break; case 'n': strncpy(name, optarg, sizeof(name) - 1); break; default: errflg++; break; } } if (strlen(mcast_dotted) == 0) errflg++; if (errflg) { fprintf(stderr, "Error parsing parameters.\n"); exit(EXIT_FAILURE); } /* initialize packets buffer */ sendbuff_init(&packets, fsize, psize); { struct sockaddr_in temp_addr; temp_addr.sin_family = AF_INET; temp_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* setup ctrl socket */ temp_addr.sin_port = htons(ctrl_port); TRY_SYS(ctrl_sock = socket(PF_INET, SOCK_DGRAM, 0)); TRY_SYS(bind(ctrl_sock, (const struct sockaddr *) &temp_addr, sizeof(temp_addr))); setup_multicast_sockopt(ctrl_sock, MCAST_TTL, MCAST_LOOPBACK); /* setup mcast socket */ temp_addr.sin_port = htons(0); TRY_TRUE(sockaddr_dotted(&mcast_addr, mcast_dotted, data_port)); TRY_SYS(mcast_sock = socket(PF_INET, SOCK_DGRAM, 0)); TRY_SYS(bind(mcast_sock, (const struct sockaddr *) &temp_addr, sizeof(temp_addr))); setup_multicast_sockopt(mcast_sock, MCAST_TTL, MCAST_LOOPBACK); TRY_SYS(connect(mcast_sock, (struct sockaddr *) &mcast_addr, sizeof(mcast_addr))); /* better to keep such things precomputed due to no-copy policy */ socklen_t addr_len = sizeof(temp_addr); TRY_SYS(getsockname(mcast_sock, (struct sockaddr *) &temp_addr, &addr_len)); ident_init(&pack_my_ident, &mcast_addr, &temp_addr, psize); strncpy(pack_my_ident.tune_name, name, sizeof(pack_my_ident.tune_name) - 1); strncpy(pack_my_ident.app_name, argv[0], sizeof(pack_my_ident.app_name) - 1); } /* NOTE: pack_ret_failed must be reinitialized before sending with proper seqno */ /* setup eventbase */ TRY_TRUE(base = event_base_new()); /* setup events */ TRY_TRUE(stdin_evt = event_new(base, 0, EV_READ|EV_PERSIST, stdin_cb, NULL)); TRY_SYS(event_add(stdin_evt, NULL)); TRY_TRUE(ctrl_evt = event_new(base, ctrl_sock, EV_READ|EV_PERSIST, ctrl_cb, NULL)); TRY_SYS(event_add(ctrl_evt, NULL)); TRY_TRUE(rtime_evt = event_new(base, -1, EV_TIMEOUT|EV_PERSIST, do_retr_cb, NULL)); struct timeval rtime_tv = {(rtime / 1000), 1000*(rtime % 1000)}; TRY_SYS(event_add(rtime_evt, &rtime_tv)); /* dispatcher loop */ TRY_SYS(event_base_dispatch(base)); /* clean exit */ event_free(stdin_evt); event_free(ctrl_evt); event_free(rtime_evt); event_base_free(base); close(mcast_sock); sendbuff_free(&packets); exit(EXIT_SUCCESS); }