int emc_connect(int plug, ushort mode, const char * ip, const ushort port){ struct easymc_plug * pg = (struct easymc_plug *)global_get_plug(plug); if(!pg){ errno = ENOPLUG; return -1; } if(pg->ipc_ || pg->tcp_){ errno = EREBIND; return -1; } if(EMC_PUB == mode)mode = EMC_SUB; if(EMC_REP == mode)mode = EMC_REQ; pg->mode = mode; if(!get_device_tcp_mgr(pg->device)){ set_device_tcp_mgr(pg->device, create_tcp_mgr(pg->device, get_device_thread(pg->device))); } if(!get_device_tcp_mgr(pg->device)){ return -1; } if(!ip || check_local_machine(inet_addr(ip))){ pg->ipc_ = create_ipc(inet_addr(ip), port, pg->device, plug, mode, EMC_REMOTE); if(!pg->ipc_){ return -1; } }else{ pg->tcp_ = add_tcp(inet_addr(ip), port, mode, EMC_REMOTE, plug, get_device_tcp_mgr(pg->device)); if(!pg->tcp_){ delete_tcp(pg->tcp_); pg->tcp_ = NULL; return -1; } } return 0; }
int emc_close(int plug){ int index = 0; void * msg = NULL; struct easymc_plug * pg = NULL; pg = (struct easymc_plug *)global_get_plug(plug); if(!pg){ errno = ENOPLUG; return -1; } del_device_plug(pg->device, plug); for(index = 0; index < 0xFFFF; index ++){ post_ringqueue(pg->mq); } if(pg->ipc_){ delete_ipc(pg->ipc_); } if(pg->tcp_){ delete_tcp(pg->tcp_); } while(1){ if(pop_ringqueue_multiple(pg->mq, (void **)&msg) < 0){ break; }else{ emc_msg_free(msg); } } delete_ringqueue(pg->mq); free(pg); global_erase_plug(plug); return 0; }
int fire_worker_start(int queue_id) { int ret, i, j, k, prot, send_ret; fire_worker_t *cc = &(workers[queue_id]); assert(ps_init_handle(&(cc->server_handle)) == 0); assert(ps_init_handle(&(cc->client_handle)) == 0); struct ps_queue server_queue, client_queue; server_queue.ifindex = config->server_ifindex; server_queue.qidx = queue_id; client_queue.ifindex = config->client_ifindex; client_queue.qidx = queue_id; assert(ps_attach_rx_device(&(cc->server_handle), &server_queue) == 0); assert(ps_attach_rx_device(&(cc->client_handle), &client_queue) == 0); struct ps_chunk client_chunk, send_client_chunk, server_chunk, send_server_chunk; assert(ps_alloc_chunk(&(cc->client_handle), &client_chunk) == 0); assert(ps_alloc_chunk(&(cc->client_handle), &send_client_chunk) == 0); assert(ps_alloc_chunk(&(cc->server_handle), &server_chunk) == 0); assert(ps_alloc_chunk(&(cc->server_handle), &send_server_chunk) == 0); client_chunk.queue.ifindex = config->client_ifindex; client_chunk.queue.qidx = queue_id; send_client_chunk.queue.ifindex = config->client_ifindex; send_client_chunk.queue.qidx = queue_id; server_chunk.queue.ifindex = config->server_ifindex; server_chunk.queue.qidx = queue_id; send_server_chunk.queue.ifindex = config->server_ifindex; send_server_chunk.queue.qidx = queue_id; int num_pkt_to_client = 0, num_pkt_to_server = 0; int pret; gettimeofday(&(cc->startime), NULL); #if defined(HIPAC_TCB) int hipac_cnt = 0; #endif for (;;) { num_pkt_to_client = 0; num_pkt_to_server = 0; j = 0; k = 0; client_chunk.cnt = config->io_batch_num; client_chunk.recv_blocking = 0; ret = ps_recv_chunk(&(cc->client_handle), &client_chunk); if (ret <= 0) { /* Receive nothing from server, go to the start of the loop to process client again */ goto process_server; } cc->total_packets += ret; int action; for (i = 0; i < ret; i ++) { prot = process_packet(client_chunk.buf + client_chunk.info[i].offset, client_chunk.info[i].len); switch (prot) { case TCP_SYN_SENT: action = HiPAC(client_chunk.buf + client_chunk.info[i].offset, client_chunk.info[i].len, l); if(action == FORWARD) { // first handshake packet // construct the response, and send back to client //fprint(INFO, "1) TCP_SYN_SENT\n"); send_client_chunk.info[j].len = client_chunk.info[i].len; send_client_chunk.info[j].offset = j * PS_MAX_PACKET_SIZE; memcpy(send_client_chunk.buf + send_client_chunk.info[j].offset, client_chunk.buf + client_chunk.info[i].offset, client_chunk.info[i].len); form_syn_response(send_client_chunk.buf + send_client_chunk.info[j].offset, send_client_chunk.info[j].len); pret = process_packet(send_client_chunk.buf + send_client_chunk.info[j].offset, send_client_chunk.info[j].len); #if 0 if(pret != TCP_SYN_RECV){ printf("pret is %d\n", pret); printf("client:\n"); dmesg(client_chunk.buf + client_chunk.info[i].offset); printf("server:\n"); dmesg(send_client_chunk.buf + send_client_chunk.info[j].offset); exit(0); } #endif assert(pret == TCP_SYN_RECV); //fprint(INFO, "2) TCP_SYN_RECV\n"); j ++; } else{ // hipac_cnt ++; // if(hipac_cnt > 0) printf("hipac filter : %d\n", hipac_cnt); delete_tcp(client_chunk.buf + client_chunk.info[i].offset); } break; case TCP_ESTABLISHED: // the 3rd handshake packet // do nothing and wait for client's real request //fprint(INFO, "3) TCP_ESTABLISHED\n"); break; case -2: //fprint(INFO, "two buckets full\n"); break; case -1: //fprint(INFO, "Error pkt, don't forward to server.\n"); break; default: // normal packet, send to server //fprint(INFO, "4) Normal packet, send to server\n"); send_server_chunk.info[k].len = client_chunk.info[i].len; send_server_chunk.info[k].offset = k * PS_MAX_PACKET_SIZE; memcpy(send_server_chunk.buf + send_server_chunk.info[k].offset, client_chunk.buf + client_chunk.info[i].offset, client_chunk.info[i].len); k ++; break; } cc->total_bytes += client_chunk.info[i].len; } if (j > 0) { //fprint(INFO, "sending %d SYN/ACK packet to client, queue_id %d, ifindex %d\n", j, queue_id, config->client_ifindex); send_client_chunk.cnt = j; send_ret = ps_send_chunk(&(cc->client_handle), &send_client_chunk); if (send_ret < 0) fprint(ERROR, "send packet fail, ret = %d\n", send_ret); } if (k > 0) { //fprint(INFO, "sending %d packets of established connection to server, queue_id %d, ifindex %d\n", k, queue_id, config->server_ifindex); send_server_chunk.cnt = k; send_ret = ps_send_chunk(&(cc->server_handle), &send_server_chunk); if (send_ret < 0) fprint(ERROR, "send packet fail, ret = %d\n", send_ret); } #if 0 /* FIXME: cannot send all packets while (ret > 0) { chunk.cnt = ret; send_ret = ps_send_chunk(&(cc->handle), &send_chunk); if (send_ret < 0) fprint(ERROR, "send packet fail, ret = %d\n", send_ret); ret -= send_ret; //assert(ret >= 0); }*/ #endif process_server: /*----------------------------------------------------------------------------------*/ /* Now process server side packet*/ server_chunk.cnt = config->io_batch_num; //server_chunk.recv_blocking = 0; //modify at the frist time server_chunk.recv_blocking = 0; j = 0; ret = ps_recv_chunk(&(cc->server_handle), &server_chunk); if (ret <= 0) { if (errno == EINTR) continue; /* Receive nothing from server, go to the start of the loop to process client again */ continue; } for (i = 0; i < ret; i ++) { prot = process_packet(server_chunk.buf + server_chunk.info[i].offset, server_chunk.info[i].len); if (prot == 0) { send_client_chunk.info[j].len = server_chunk.info[i].len; send_client_chunk.info[j].offset = j * PS_MAX_PACKET_SIZE; memcpy(send_client_chunk.buf + send_client_chunk.info[j].offset, server_chunk.buf + server_chunk.info[i].offset, server_chunk.info[i].len); j ++; } else { fprint(ERROR, "wrong packet from server\n"); } } if (j > 0) { fprint(DEBUG, "sending packet, queue_id %d, num %d, index %d\n", queue_id, ret, config->client_ifindex); send_client_chunk.cnt = j; send_ret = ps_send_chunk(&(cc->client_handle), &send_client_chunk); if (send_ret < 0) fprint(ERROR, "send packet fail, ret = %d\n", send_ret); } } return 0; }