Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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);  
}
Пример #4
0
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;
}
Пример #5
0
/*!
 * \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, &param);

	/* 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;
}