/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++* * free_mbuff_locking() * *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void free_mbuff_locking(struct mbuff *m) { pthread_mutex_lock(&heap_mbuff_mutex); free_mbuff(m); pthread_mutex_unlock(&heap_mbuff_mutex); return; }
int udp_Read (int sockid, caddr_t data, int size) { int read; struct mbuff *mbuffer; udp_Socket *sock = (udp_Socket *) scheduler.sockets[sockid].ptr; if (sock->myport == 0) /* minimal error checking */ { SET_ERR (SCPS_EBADF); return (-1); } /* If there is no mbuff and associated data available, then we block */ if (!(mbuffer = sock->receive_buff->start)) { ((tp_Socket *) scheduler.sockets[sockid].ptr)->thread->status = Blocked; scheduler.num_runable--; scheduler.sockets[sockid].read = 1; sched (); mbuffer = sock->receive_buff->start; } /* * Make sure the size request is less than or equal * to the amount of memory we have available to this connection */ if (size > mbuffer->m_ext.len) size = mbuffer->m_ext.len; /* * At this point, it should just be a matter * of doing a cb_cpdatout() into the data pointer... */ read = cb_cpdatout (sock->app_rbuff, data, size); #ifndef GATEWAY if (!(sock->app_rbuff->size)) sock->thread->read_socks &= ~(1 << sock->sockid); #endif /* GATEWAY */ if (read == 0) { printf ("cb_cpdatout returns 0\t"); printf ("size = %d, app rbuff size = %d\n", size, (int) sock->app_rbuff->size); SET_ERR (SCPS_EWOULDBLOCK); return (-1); } /* Trim off the associated mbuff from the receive-buffer. */ /* mb_rtrim (sock->receive_buff, read); */ mbuffer = deq_mbuff (sock->receive_buff); free_mbuff (mbuffer); return (read); }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++* * alloc_mbuff_chain() * *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ size_t alloc_mbuff_chain( struct msg_queue *queue, size_t len) { struct msg *p_buff; struct mbuff *m_buff; size_t i; /* * 1- Block mutex msg * 2- Block mutex mbuff * 3- Create n mbuff elements * 4- Create n pkbuff elements * 5- Unblock mutex mbuff * 6- Unblock mutex msg */ pthread_mutex_lock(&heap_msg_mutex); pthread_mutex_lock(&heap_mbuff_mutex); for ( i = 0; i <= len-1 ; i++ ) { m_buff = alloc_mbuff(); if (m_buff != NULL) { p_buff = alloc_msg(); if (p_buff != NULL) { p_buff->p_next = NULL; p_buff->mb.mbp = m_buff; msg_enqueue(queue, p_buff); } else { free_mbuff(m_buff); break; } } else break; } pthread_mutex_unlock(&heap_mbuff_mutex); pthread_mutex_unlock(&heap_msg_mutex); return i; }
/* * Try to send the UDP datagram. Enqueue at most * one UDP datagram if there's room, and then try * to send it. Return the number of bytes queued. * Otherwise, throw away the data, return -1 and * set EWOULDBLOCK for non-blocking, or just block. * * This will need to be modified to provide a way * for the application to flush the one-datagram * buffer. timer? "system call"? later */ int udp_WriteTo (int sockid, byte * dp, int len, scps_np_addr ina, word port) { uint32_t bytes_sent = 0; #ifdef SCPSSP int temp; #endif /* SCPSSP */ int cc = 0; struct mbuff *mbuffer; struct mbcluster *mbcluster; udp_Socket *s = (udp_Socket *) scheduler.sockets[sockid].ptr; if (s->myport == 0) /* minimal error checking */ { SET_ERR (SCPS_EBADF); goto cleanup; return (-1); } if (len > MAX_UDP_PAYLOAD) /* enforce max UDP datagram size ??????? */ { SET_ERR (SCPS_EMSGSIZE); goto cleanup; return (-1); } if ((s->rt_route->MTU) && /* enforce MTU */ ((len + UDP_HDR_LEN + s->np_size + s->sp_size) > s->rt_route->MTU)) { SET_ERR (SCPS_EMSGSIZE); goto cleanup; return (-1); } if ((s->rt_route && s->rt_route->flags & RT_LINK_AVAIL) && (s->rt_route->current_credit >= ((int) s->send_buff->start->m_ext.len + UDP_HDR_LEN + s->sp_size + 20))) /* hard-coded for IP! */ { s->buff_full = FALSE; } if (s->buff_full) { SET_ERR (SCPS_ENOBUFS); goto cleanup; return (-1); } if ((cb_cpdatin (s->app_sbuff, dp, len, 0, 0)) != len) { SET_ERR (SCPS_ENOBUFS); goto cleanup; return (-1); } s->ph.nl_head.ipv4.dst = ina; s->hisport = port; s->his_ipv4_addr = htonl ((uint32_t) ina); /* Build the packet! */ if ((mcput (s->send_buff->start, s->app_sbuff->start, s->app_sbuff->read_off, len, 1)) != len) { printf ("\nbigs problems in udp_WriteTo()\n"); fflush (stdout); return (-1); } /* Fill in the requirements structure */ s->np_rqts.tpid = SCPSUDP; s->np_rqts.ipv4_dst_addr = htonl (ina); #ifdef UDP_GATEWAY s->np_rqts.ipv4_src_addr = s->my_ipv4_addr; #else /* UDP_GATEWAY */ s->np_rqts.ipv4_src_addr = ntohl (local_addr); #endif /* UDP_GATEWAY */ s->np_rqts.timestamp.format = 0; s->np_rqts.timestamp.ts_val[0] = s->np_rqts.timestamp.ts_val[1] = 0; /* s->np_rqts.bqos.precedence = rqts->bqos.precedence; */ s->np_rqts.bqos.routing = 0; s->np_rqts.bqos.pro_specific = 0; s->np_rqts.eqos.ip_precedence = 0; s->np_rqts.eqos.ip_tos = 0; s->np_rqts.cksum = 0; s->np_rqts.int_del = 0; s->np_rqts.nl_protocol = nl_default; #ifdef SCPSSP /* Fill in the SP requirements structure */ s->sp_rqts.np_rqts.tpid = SP; s->sp_rqts.np_rqts.ipv4_dst_addr = htonl (ina); #ifdef UDP_GATEWAY s->sp_rqts.np_rqts.ipv4_src_addr = s->myaddr; #else /* UDP_GATEWAY */ s->sp_rqts.np_rqts.ipv4_src_addr = ntohl (local_addr); #endif /* UDP_GATEWAY */ s->sp_rqts.np_rqts.timestamp.format = 0; s->sp_rqts.np_rqts.timestamp.ts_val[0] = s->sp_rqts.np_rqts.timestamp.ts_val[1] = 0; s->sp_rqts.np_rqts.bqos.precedence = 0; /* rqts->bqos.precedence; */ /* s->sp_rqts.np_rqts.bqos.routing = rqts->bqos.precedence; */ s->sp_rqts.np_rqts.bqos.pro_specific = 0; s->sp_rqts.np_rqts.eqos.ip_precedence = 0; s->sp_rqts.np_rqts.eqos.ip_tos = 0; s->sp_rqts.np_rqts.cksum = 0; /* rqts->cksum; */ s->sp_rqts.np_rqts.int_del = 0; s->sp_rqts.np_rqts.nl_protocol = nl_default; s->sp_rqts.tpid = SCPSUDP; s->sp_rqts.sprqts = 0; s->np_rqts.tpid = SP; #ifdef SECURE_GATEWAY s->sp_rqts.secure_gateway_rqts = s->rt_route->secure_gateway_rqts; #endif /* SECURE_GATEWAY */ s->sp_size = sp_hdr_size (s->sp_rqts); temp = s->sp_size + (s->sp_size % sizeof (uint32_t)); s->sh_off = s->th_off - temp; #endif /* SCPSSP */ switch (s->np_rqts.nl_protocol) { case NL_PROTOCOL_IPV4: s->np_size = ip_get_template (&(s->np_rqts), &(s->ip_templ)); break; case NL_PROTOCOL_NP: s->np_size = scps_np_get_template (&(s->np_rqts), &(s->np_templ)); break; } udp_BuildHdr (s, s->send_buff->start); s->app_sbuff->size -= len; /* size should be zero now! */ s->buff_full = TRUE; if ((s->rt_route && s->rt_route->flags & RT_LINK_AVAIL) && (s->rt_route->current_credit >= ((int) s->send_buff->start->m_ext.len + UDP_HDR_LEN + s->sp_size + 20))) /* hard-coded for IP! */ { cc = udp_Coalesce (s, &bytes_sent); bytes_sent = len; s->buff_full = FALSE; /* Let them know how much data we actually wrote to the transport */ if (cc > 0) s->user_data += len; } cleanup: /* * This all looks kind of crusty */ /* dequeue all clusters */ for (mbcluster = deq_mclus (s->app_sbuff); mbcluster; mbcluster = deq_mclus (s->app_sbuff)) free_mclus (mbcluster); s->app_sbuff->read_head = s->app_sbuff->write_head = NULL; s->app_sbuff->write_off = s->app_sbuff->bytes_beyond = 0; mbuffer = deq_mbuff (s->send_buff); free_mbuff (mbuffer); /* free mbuff and all clusters */ if (!(mbuffer = alloc_mbuff (MT_HEADER))) /* get back our mbuff */ { SET_ERR (SCPS_ENOMEM); exit (-1); /* not the thing to do */ } if (!(enq_mbuff (mbuffer, s->send_buff))) printf ("MBUFFER ENQUEUEING ERROR in udp_Coalesce()\n"); if (cc) return (len); else { SET_ERR (SCPS_ENOBUFS); return (-1); } }