/* finds a connection, if id=0 uses the ip addr & port (host byte order) * WARNING: unprotected (locks) use tcpconn_get unless you really * know what you are doing */ struct tcp_connection* _tcpconn_find(int id, struct ip_addr* ip, int port) { struct tcp_connection *c; unsigned hash; #ifdef EXTRA_DEBUG DBG("tcpconn_find: %d port %d\n",id, port); print_ip("tcpconn_find: ip ", ip, "\n"); #endif if (id){ hash=tcp_id_hash(id); for (c=tcpconn_id_hash[hash]; c; c=c->id_next){ #ifdef EXTRA_DEBUG DBG("c=%p, c->id=%d, port=%d\n",c, c->id, c->rcv.src_port); print_ip("ip=", &c->rcv.src_ip, "\n"); #endif if ((id==c->id)&&(c->state!=S_CONN_BAD)) return c; } }else if (ip){ hash=tcp_addr_hash(ip, port); for (c=tcpconn_addr_hash[hash]; c; c=c->next){ #ifdef EXTRA_DEBUG DBG("c=%p, c->id=%d, port=%d\n",c, c->id, c->rcv.src_port); print_ip("ip=",&c->rcv.src_ip,"\n"); #endif if ( (c->state!=S_CONN_BAD) && (port==c->rcv.src_port) && (ip_addr_cmp(ip, &c->rcv.src_ip)) ) return c; } } return 0; }
/*! \brief finds a connection, if id=0 uses the ip addr & port (host byte order) * \note WARNING: unprotected (locks) use tcpconn_get unless you really * know what you are doing */ struct tcp_connection* _tcpconn_find(int id, struct ip_addr* ip, int port) { struct tcp_connection *c; struct tcp_conn_alias* a; unsigned hash; #ifdef EXTRA_DEBUG LM_DBG("%d port %d\n",id, port); if (ip) print_ip("tcpconn_find: ip ", ip, "\n"); #endif if (id){ hash=tcp_id_hash(id); for (c=tcpconn_id_hash[hash]; c; c=c->id_next){ #ifdef EXTRA_DEBUG LM_DBG("c=%p, c->id=%d, port=%d\n",c, c->id, c->rcv.src_port); print_ip("ip=", &c->rcv.src_ip, "\n"); #endif if ((id==c->id)&&(c->state!=S_CONN_BAD)) return c; } }else if (ip){ hash=tcp_addr_hash(ip, port); for (a=tcpconn_aliases_hash[hash]; a; a=a->next){ #ifdef EXTRA_DEBUG LM_DBG("a=%p, c=%p, c->id=%d, alias port= %d port=%d\n", a, a->parent, a->parent->id, a->port, a->parent->rcv.src_port); print_ip("ip=",&a->parent->rcv.src_ip,"\n"); #endif if ( (a->parent->state!=S_CONN_BAD) && (port==a->port) && (ip_addr_cmp(ip, &a->parent->rcv.src_ip)) ) return a->parent; } } return 0; }
struct tcp_connection* tcpconn_add(struct tcp_connection *c) { unsigned hash; if (c){ TCPCONN_LOCK; /* add it at the begining of the list*/ hash=tcp_id_hash(c->id); c->id_hash=hash; tcpconn_listadd(tcpconn_id_hash[hash], c, id_next, id_prev); hash=tcp_addr_hash(&c->rcv.src_ip, c->rcv.src_port); /* set the first alias */ c->con_aliases[0].port=c->rcv.src_port; c->con_aliases[0].hash=hash; c->con_aliases[0].parent=c; tcpconn_listadd(tcpconn_aliases_hash[hash], &c->con_aliases[0], next, prev); c->aliases++; TCPCONN_UNLOCK; LM_DBG("hashes: %d, %d\n", hash, c->id_hash); return c; }else{ LM_CRIT("null connection pointer\n"); return 0; } }
/*! \brief finds a connection, if id=0 return NULL * \note WARNING: unprotected (locks) use tcpconn_get unless you really * know what you are doing */ static struct tcp_connection* _tcpconn_find(int id) { struct tcp_connection *c; unsigned hash; if (id){ hash=tcp_id_hash(id); for (c=TCP_PART(id).tcpconn_id_hash[hash]; c; c=c->id_next){ #ifdef EXTRA_DEBUG LM_DBG("c=%p, c->id=%d, port=%d\n",c, c->id, c->rcv.src_port); print_ip("ip=", &c->rcv.src_ip, "\n"); #endif if ((id==c->id)&&(c->state!=S_CONN_BAD)) return c; } } return 0; }
struct tcp_connection* tcpconn_add(struct tcp_connection *c) { unsigned hash; if (c){ TCPCONN_LOCK; /* add it at the begining of the list*/ hash=tcp_addr_hash(&c->rcv.src_ip, c->rcv.src_port); c->addr_hash=hash; tcpconn_listadd(tcpconn_addr_hash[hash], c, next, prev); hash=tcp_id_hash(c->id); c->id_hash=hash; tcpconn_listadd(tcpconn_id_hash[hash], c, id_next, id_prev); TCPCONN_UNLOCK; DBG("tcpconn_add: hashes: %d, %d\n", c->addr_hash, c->id_hash); return c; }else{ LOG(L_CRIT, "tcpconn_add: BUG: null connection pointer\n"); return 0; } }
ws_connection_t *wsconn_get(int id) { int id_hash = tcp_id_hash(id); ws_connection_t *wsc; LM_DBG("wsconn_get for id [%d]\n", id); WSCONN_LOCK; for (wsc = wsconn_id_hash[id_hash]; wsc; wsc = wsc->id_next) { if (wsc->id == id) { wsconn_ref(wsc); LM_DBG("wsconn_get returns wsc [%p] refcnt [%d]\n", wsc, atomic_get(&wsc->refcnt)); WSCONN_UNLOCK; return wsc; } } WSCONN_UNLOCK; return NULL; }
int wsconn_add(struct receive_info rcv, unsigned int sub_protocol) { int cur_cons, max_cons; int id = rcv.proto_reserved1; int id_hash = tcp_id_hash(id); ws_connection_t *wsc; LM_DBG("wsconn_add id [%d]\n", id); /* Allocate and fill in new WebSocket connection */ wsc = shm_malloc(sizeof(ws_connection_t) + BUF_SIZE); if (wsc == NULL) { LM_ERR("allocating shared memory\n"); return -1; } memset(wsc, 0, sizeof(ws_connection_t) + BUF_SIZE); wsc->id = id; wsc->id_hash = id_hash; wsc->state = WS_S_OPEN; wsc->rcv = rcv; wsc->sub_protocol = sub_protocol; wsc->run_event = 0; wsc->frag_buf.s = ((char*)wsc) + sizeof(ws_connection_t); atomic_set(&wsc->refcnt, 0); LM_DBG("wsconn_add new wsc => [%p], ref => [%d]\n", wsc, atomic_get(&wsc->refcnt)); WSCONN_LOCK; /* Add to WebSocket connection table */ wsconn_listadd(wsconn_id_hash[wsc->id_hash], wsc, id_next, id_prev); /* Add to the end of the WebSocket used list */ wsc->last_used = (int)time(NULL); if (wsconn_used_list->head == NULL) wsconn_used_list->head = wsconn_used_list->tail = wsc; else { wsc->used_prev = wsconn_used_list->tail; wsconn_used_list->tail->used_next = wsc; wsconn_used_list->tail = wsc; } wsconn_ref(wsc); WSCONN_UNLOCK; LM_DBG("wsconn_add added to conn_table wsc => [%p], ref => [%d]\n", wsc, atomic_get(&wsc->refcnt)); /* Update connection statistics */ lock_get(wsstat_lock); update_stat(ws_current_connections, 1); cur_cons = get_stat_val(ws_current_connections); max_cons = get_stat_val(ws_max_concurrent_connections); if (max_cons < cur_cons) update_stat(ws_max_concurrent_connections, cur_cons - max_cons); if (wsc->sub_protocol == SUB_PROTOCOL_SIP) { update_stat(ws_sip_current_connections, 1); cur_cons = get_stat_val(ws_sip_current_connections); max_cons = get_stat_val(ws_sip_max_concurrent_connections); if (max_cons < cur_cons) update_stat(ws_sip_max_concurrent_connections, cur_cons - max_cons); } else if (wsc->sub_protocol == SUB_PROTOCOL_MSRP) { update_stat(ws_msrp_current_connections, 1); cur_cons = get_stat_val(ws_msrp_current_connections); max_cons = get_stat_val(ws_msrp_max_concurrent_connections); if (max_cons < cur_cons) update_stat(ws_msrp_max_concurrent_connections, cur_cons - max_cons); } lock_release(wsstat_lock); return 0; }