static int request_recv(struct knot_request *request, const struct timeval *timeout) { knot_pkt_t *resp = request->resp; knot_pkt_clear(resp); /* Each request has unique timeout. */ struct timeval tv = { timeout->tv_sec, timeout->tv_usec }; /* Wait for readability */ int ret = request_ensure_connected(request); if (ret != KNOT_EOK) { return ret; } /* Receive it */ if (use_tcp(request)) { ret = tcp_recv_msg(request->fd, resp->wire, resp->max_size, &tv); } else { ret = udp_recv_msg(request->fd, resp->wire, resp->max_size, &tv); } if (ret <= 0) { resp->size = 0; if (ret == 0) { return KNOT_ECONN; } return ret; } resp->size = ret; return ret; }
static void* responder_thread(void *arg) { int fd = *((int *)arg); uint8_t buf[KNOT_WIRE_MAX_PKTSIZE]; while(true) { int client = accept(fd, NULL, NULL); if (client < 0) { break; } int len = tcp_recv_msg(client, buf, sizeof(buf), NULL); if (len < KNOT_WIRE_HEADER_SIZE) { close(client); break; } knot_wire_set_qr(buf); tcp_send_msg(client, buf, len, NULL); close(client); } return NULL; }
void ServerConnection::receive() { int res = tcp_recv_msg(conn.dia_conn, &conn.rb, 0, CONN_WAIT_USECS); if (res < 0) { if (res == AAA_CONN_SHUTDOWN) { INFO( M_NAME "receive(): shutdown - closing connection.\n"); closeConnection(true); } else { closeConnection(); ERROR( M_NAME "receive(): tcp_recv_reply() failed.\n"); } return; } if (!res) // nothing received return; /* obtain the structure corresponding to the message */ AAAMessage* msg = AAATranslateMessage(conn.rb.buf, conn.rb.buf_len, 0); if(!msg) { ERROR( M_NAME "receive(): message structure not obtained from message.\n"); closeConnection(); return; } #ifdef EXTRA_DEBUG AAAPrintMessage(msg); #endif if (is_req(msg)) handleRequest(msg); else handleReply(msg); AAAFreeMessage(&msg); }
void ServerConnection::openConnection() { DBG("init TCP connection\n"); if (conn.dia_conn) { ERROR("CRITICAL: trying to open new connection, while current one still" " opened.\n"); abort(); } conn.dia_conn = tcp_create_connection(server_name.c_str(), server_port, ca_file.c_str(), cert_file.c_str()); if (!conn.dia_conn) { ERROR("establishing connection to %s\n", server_name.c_str()); setRetryConnectLater(); return; } // send CER AAAMessage* cer; if ((cer=AAAInMessage(AAA_CC_CER, AAA_APP_DIAMETER_COMMON_MSG))==NULL) { ERROR(M_NAME":openConnection(): can't create new " "CER AAA message!\n"); conn.terminate(); setRetryConnectLater(); return; } if (addOrigin(cer) || addDataAVP(cer, AVP_Host_IP_Address, origin_ip_address, sizeof(origin_ip_address)) || addDataAVP(cer, AVP_Vendor_Id, (char*)&vendorID, sizeof(vendorID)) || addDataAVP(cer, AVP_Supported_Vendor_Id, (char*)&vendorID, sizeof(vendorID)) || addStringAVP(cer, AVP_Product_Name, product_name)) { ERROR("openConnection(): adding AVPs failed\n"); conn.terminate(); setRetryConnectLater(); return; } // supported applications AAA_AVP* vs_appid; if( (vs_appid=AAACreateAVP(AVP_Vendor_Specific_Application_Id, (AAA_AVPFlag)AAA_AVP_FLAG_NONE, 0, 0, 0, AVP_DONT_FREE_DATA)) == 0) { ERROR( M_NAME":openConnection(): creating AVP failed." " (no more free memory!)\n"); conn.terminate(); setRetryConnectLater(); return; } // feels like c coding... if (addGroupedAVP(vs_appid, AVP_Auth_Application_Id, (char*)&app_id, sizeof(app_id)) || addGroupedAVP(vs_appid, AVP_Vendor_Id, (char*)&vendorID, sizeof(vendorID)) || (AAAAddAVPToMessage(cer, vs_appid, 0) != AAA_ERR_SUCCESS) ) { ERROR( M_NAME":openConnection(): creating AVP failed." " (no more free memory!)\n"); conn.terminate(); setRetryConnectLater(); return; } #ifdef EXTRA_DEBUG AAAPrintMessage(cer); #endif conn.setIDs(cer); if(AAABuildMsgBuffer(cer) != AAA_ERR_SUCCESS) { ERROR( " openConnection(): message buffer not created\n"); AAAFreeMessage(&cer); return; } int ret = tcp_send(conn.dia_conn, cer->buf.s, cer->buf.len); if (ret) { ERROR( "openConnection(): could not send message\n"); conn.terminate(); setRetryConnectLater(); AAAFreeMessage(&cer); return; } AAAFreeMessage(&cer); unsigned int cea_receive_cnt = 3; while (true) { int res = tcp_recv_msg(conn.dia_conn, &conn.rb, CONNECT_CEA_REPLY_TIMEOUT, 0); if (res <= 0) { if (!res) { ERROR( " openConnection(): did not receive response (CEA).\n"); } else { ERROR( " openConnection(): error receiving response (CEA).\n"); } conn.terminate(); setRetryConnectLater(); return; } /* obtain the structure corresponding to the message */ AAAMessage* cea = AAATranslateMessage(conn.rb.buf, conn.rb.buf_len, 0); if(!cea) { ERROR( " openConnection(): could not decipher response (CEA).\n"); conn.terminate(); setRetryConnectLater(); return; } if (cea->commandCode == AAA_CC_CEA) { #ifdef EXTRA_DEBUG AAAPrintMessage(cea); #endif AAAFreeMessage(&cea); break; } AAAFreeMessage(&cea); if (!(cea_receive_cnt--)) { ERROR( " openConnection(): no CEA received.\n"); conn.terminate(); setRetryConnectLater(); return; } } DBG("Connection opened.\n"); open = true; }
/*! * \brief TCP event handler function. */ static int tcp_handle(tcp_context_t *tcp, int fd, struct iovec *rx, struct iovec *tx) { /* Create query processing parameter. */ struct sockaddr_storage ss; memset(&ss, 0, sizeof(struct sockaddr_storage)); struct process_query_param param = {0}; param.socket = fd; param.remote = &ss; param.server = tcp->server; param.thread_id = tcp->thread_id; rx->iov_len = KNOT_WIRE_MAX_PKTSIZE; tx->iov_len = KNOT_WIRE_MAX_PKTSIZE; /* Receive peer name. */ socklen_t addrlen = sizeof(struct sockaddr_storage); if (getpeername(fd, (struct sockaddr *)&ss, &addrlen) < 0) { ; } /* Timeout. */ struct timeval tmout = { conf()->max_conn_reply, 0 }; /* Receive data. */ int ret = tcp_recv_msg(fd, rx->iov_base, rx->iov_len, &tmout); if (ret <= 0) { dbg_net("tcp: client on fd=%d disconnected\n", fd); if (ret == KNOT_EAGAIN) { rcu_read_lock(); char addr_str[SOCKADDR_STRLEN] = {0}; sockaddr_tostr(addr_str, sizeof(addr_str), &ss); log_warning("connection timed out, address '%s', " "timeout %d seconds", addr_str, conf()->max_conn_idle); rcu_read_unlock(); } return KNOT_ECONNREFUSED; } else { rx->iov_len = ret; } /* Create packets. */ mm_ctx_t *mm = tcp->overlay.mm; knot_pkt_t *ans = knot_pkt_new(tx->iov_base, tx->iov_len, mm); knot_pkt_t *query = knot_pkt_new(rx->iov_base, rx->iov_len, mm); /* Initialize processing overlay. */ knot_overlay_init(&tcp->overlay, mm); knot_overlay_add(&tcp->overlay, NS_PROC_QUERY, ¶m); /* Input packet. */ int state = knot_overlay_in(&tcp->overlay, query); /* Resolve until NOOP or finished. */ ret = KNOT_EOK; while (state & (KNOT_NS_PROC_FULL|KNOT_NS_PROC_FAIL)) { state = knot_overlay_out(&tcp->overlay, ans); /* Send, if response generation passed and wasn't ignored. */ if (ans->size > 0 && !(state & (KNOT_NS_PROC_FAIL|KNOT_NS_PROC_NOOP))) { if (tcp_send_msg(fd, ans->wire, ans->size) != ans->size) { ret = KNOT_ECONNREFUSED; break; } } } /* Reset after processing. */ knot_overlay_finish(&tcp->overlay); knot_overlay_deinit(&tcp->overlay); /* Cleanup. */ knot_pkt_free(&query); knot_pkt_free(&ans); return ret; }