Esempio n. 1
0
struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
{
	int s;
	struct socket_info* si;
	union sockaddr_union my_name;
	socklen_t my_name_len;
	struct tcp_connection* con;
	struct ip_addr ip;

	s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
	if (s==-1){
		LOG(L_ERR, "ERROR: tcpconn_connect: socket: (%d) %s\n",
				errno, strerror(errno));
		goto error;
	}
	if (init_sock_opt(s)<0){
		LOG(L_ERR, "ERROR: tcpconn_connect: init_sock_opt failed\n");
		goto error;
	}
	if (tcp_blocking_connect(s, &server->s, sockaddru_len(*server))<0){
		LOG(L_ERR, "ERROR: tcpconn_connect: tcp_blocking_connect failed\n");
		goto error;
	}
	my_name_len=sizeof(my_name);
	if (getsockname(s, &my_name.s, &my_name_len)!=0){
		LOG(L_ERR, "ERROR: tcp_connect: getsockname failed: %s(%d)\n",
				strerror(errno), errno);
		si=0; /* try to go on */
	}
	su2ip_addr(&ip, &my_name);
#ifdef USE_TLS
	if (type==PROTO_TLS)
		si=find_si(&ip, 0, PROTO_TLS);
	else
#endif
		si=find_si(&ip, 0, PROTO_TCP);

	if (si==0){
		LOG(L_ERR, "ERROR: tcp_connect: could not find corresponding"
				" listening socket, using default...\n");
		if (server->s.sa_family==AF_INET) si=sendipv4_tcp;
#ifdef USE_IPV6
		else si=sendipv6_tcp;
#endif
	}
	con=tcpconn_new(s, server, si, type, S_CONN_CONNECT);
	if (con==0){
		LOG(L_ERR, "ERROR: tcp_connect: tcpconn_new failed, closing the "
				 " socket\n");
		goto error;
	}
	return con;
	/*FIXME: set sock idx! */
error:
	if (s!=-1) close(s); /* close the opened socket */
	return 0;
}
Esempio n. 2
0
/*! \brief
 * handles a new connection, called internally by tcp_main_loop/handle_io.
 * \param si - pointer to one of the tcp socket_info structures on which
 *              an io event was detected (connection attempt)
 * \return  handle_* return convention: -1 on error, 0 on EAGAIN (no more
 *           io events queued), >0 on success. success/error refer only to
 *           the accept.
 */
static inline int handle_new_connect(struct socket_info* si)
{
	union sockaddr_union su;
	struct tcp_connection* tcpconn;
	socklen_t su_len;
	int new_sock;
	int id;

	/* got a connection on r */
	su_len=sizeof(su);
	new_sock=accept(si->socket, &(su.s), &su_len);
	if (new_sock==-1){
		if ((errno==EAGAIN)||(errno==EWOULDBLOCK))
			return 0;
		LM_ERR("failed to accept connection(%d): %s\n", errno, strerror(errno));
		return -1;
	}
	if (tcp_connections_no>=tcp_max_connections){
		LM_ERR("maximum number of connections exceeded: %d/%d\n",
					tcp_connections_no, tcp_max_connections);
		close(new_sock);
		return 1; /* success, because the accept was succesfull */
	}
	if (tcp_init_sock_opt(new_sock)<0){
		LM_ERR("tcp_init_sock_opt failed\n");
		close(new_sock);
		return 1; /* success, because the accept was succesfull */
	}

	/* add socket to list */
	tcpconn=tcpconn_new(new_sock, &su, si, S_CONN_OK, F_CONN_ACCEPTED);
	if (tcpconn){
		tcpconn->refcnt++; /* safe, not yet available to the
							  outside world */
		tcpconn_add(tcpconn);
		LM_DBG("new connection: %p %d flags: %04x\n",
				tcpconn, tcpconn->s, tcpconn->flags);
		/* pass it to a child */
		if(send2child(tcpconn,IO_WATCH_READ)<0){
			LM_ERR("no children available\n");
			id = tcpconn->id;
			TCPCONN_LOCK(id);
			tcpconn->refcnt--;
			if (tcpconn->refcnt==0){
				_tcpconn_rm(tcpconn);
				close(new_sock/*same as tcpconn->s*/);
			}else tcpconn->lifetime=0; /* force expire */
			TCPCONN_UNLOCK(id);
		}
	}else{ /*tcpconn==0 */
		LM_ERR("tcpconn_new failed, closing socket\n");
		close(new_sock);
	}
	return 1; /* accept() was succesfull */
}
Esempio n. 3
0
/* handle a new connection, called internally by tcp_main_loop */
static inline void handle_new_connect(struct socket_info* si,
										fd_set* sel_set, int* n)
{
	union sockaddr_union su;
	struct tcp_connection* tcpconn;
	socklen_t su_len;
	int new_sock;
	
	if ((FD_ISSET(si->socket, sel_set))){
		/* got a connection on r */
		su_len=sizeof(su);
		new_sock=accept(si->socket, &(su.s), &su_len);
		(*n)--;
		if (new_sock==-1){
			LOG(L_ERR,  "WARNING: tcp_main_loop: error while accepting"
					" connection(%d): %s\n", errno, strerror(errno));
			return;
		}
		if (init_sock_opt(new_sock)<0){
			LOG(L_ERR, "ERROR: tcp_main_loop: init_sock_opt failed\n");
			close(new_sock);
			return;
		}
		
		/* add socket to list */
		tcpconn=tcpconn_new(new_sock, &su, si, si->proto, S_CONN_ACCEPT);
		if (tcpconn){
			tcpconn->refcnt++; /* safe, not yet available to the
								  outside world */
			tcpconn_add(tcpconn);
			DBG("tcp_main_loop: new connection: %p %d\n",
				tcpconn, tcpconn->s);
			/* pass it to a child */
			if(send2child(tcpconn)<0){
				LOG(L_ERR,"ERROR: tcp_main_loop: no children "
						"available\n");
				TCPCONN_LOCK;
				tcpconn->refcnt--;
				if (tcpconn->refcnt==0){
					close(tcpconn->s);
					_tcpconn_rm(tcpconn);
				}else tcpconn->timeout=0; /* force expire */
				TCPCONN_UNLOCK;
			}
		}else{ /*tcpconn==0 */
			LOG(L_ERR, "ERROR: tcp_main_loop: tcpconn_new failed, "
					"closing socket\n");
			close(new_sock);
		}
	}
}
Esempio n. 4
0
struct tcp_connection* tcp_conn_new(int sock, union sockaddr_union* su,
		struct socket_info* si, int state)
{
	struct tcp_connection *c;

	/* create the connection structure */
	c = tcpconn_new(sock, su, si, state, 0);
	if (c==NULL) {
		LM_ERR("tcpconn_new failed\n");
		return NULL;
	}
	c->refcnt++; /* safe to do it w/o locking, it's not yet
					available to the rest of the world */

	return c;
}
Esempio n. 5
0
struct tcp_connection* tcpconn_connect(struct socket_info* send_sock,
		union sockaddr_union* server, int type)
{
	int s;
	union sockaddr_union my_name;
	socklen_t my_name_len;
	struct tcp_connection* con;

	s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
	if (s==-1){
		LM_ERR("socket: (%d) %s\n", errno, strerror(errno));
		goto error;
	}
	if (init_sock_opt(s)<0){
		LM_ERR("init_sock_opt failed\n");
		goto error;
	}
	my_name_len = sockaddru_len(send_sock->su);
	memcpy( &my_name, &send_sock->su, my_name_len);
	su_setport( &my_name, 0);
	if (bind(s, &my_name.s, my_name_len )!=0) {
		LM_ERR("bind failed (%d) %s\n", errno,strerror(errno));
		goto error;
	}

	if (tcp_blocking_connect(s, &server->s, sockaddru_len(*server))<0){
		LM_ERR("tcp_blocking_connect failed\n");
		goto error;
	}
	con=tcpconn_new(s, server, send_sock, type, S_CONN_CONNECT);
	if (con==0){
		LM_ERR("tcpconn_new failed, closing the socket\n");
		goto error;
	}
	return con;
	/*FIXME: set sock idx! */
error:
	if (s!=-1) close(s); /* close the opened socket */
	return 0;
}