00001 /** @file 00002 00003 A brief file description 00004 00005 @section license License 00006 00007 Licensed to the Apache Software Foundation (ASF) under one 00008 or more contributor license agreements. See the NOTICE file 00009 distributed with this work for additional information 00010 regarding copyright ownership. The ASF licenses this file 00011 to you under the Apache License, Version 2.0 (the 00012 "License"); you may not use this file except in compliance 00013 with the License. You may obtain a copy of the License at 00014 00015 http://www.apache.org/licenses/LICENSE-2.0 00016 00017 Unless required by applicable law or agreed to in writing, software 00018 distributed under the License is distributed on an "AS IS" BASIS, 00019 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00020 See the License for the specific language governing permissions and 00021 limitations under the License. 00022 */ 00023 00024 /**************************************************************************** 00025 00026 UnixUDPConnection.cc 00027 Unix UDPConnection implementation 00028 00029 00030 ****************************************************************************/ 00031 00032 #include "P_Net.h" 00033 #include "P_UDPNet.h" 00034 00035 UnixUDPConnection::~UnixUDPConnection() 00036 { 00037 UDPPacketInternal *p = (UDPPacketInternal *) ink_atomiclist_popall(&inQueue); 00038 00039 if (!tobedestroyed) 00040 tobedestroyed = 1; 00041 00042 if (p) { 00043 UDPPacketInternal *pnext = NULL; 00044 while (p) { 00045 pnext = p->alink.next; 00046 p->alink.next = NULL; 00047 p->free(); 00048 p = pnext; 00049 } 00050 } 00051 if (callbackAction) { 00052 callbackAction->cancel(); 00053 callbackAction = NULL; 00054 } 00055 Debug("udpnet", "Destroying udp port = %d", getPortNum()); 00056 if (fd != NO_FD) { 00057 socketManager.close(fd); 00058 } 00059 fd = NO_FD; 00060 } 00061 00062 // called with continuation lock taken out 00063 // We call Release because AddRef was called before entering here. 00064 int 00065 UnixUDPConnection::callbackHandler(int event, void *data) 00066 { 00067 (void) event; 00068 (void) data; 00069 callbackAction = NULL; 00070 if (continuation == NULL) 00071 return EVENT_CONT; 00072 00073 if (m_errno) { 00074 if (!shouldDestroy()) 00075 continuation->handleEvent(NET_EVENT_DATAGRAM_ERROR, this); 00076 destroy(); // don't destroy until after calling back with error 00077 Release(); 00078 return EVENT_CONT; 00079 } else { 00080 UDPPacketInternal *p = (UDPPacketInternal *) ink_atomiclist_popall(&inQueue); 00081 if (p) { 00082 Debug("udpnet", "UDPConnection::callbackHandler"); 00083 UDPPacketInternal *pnext = NULL; 00084 Queue<UDPPacketInternal> result; 00085 while (p) { 00086 pnext = p->alink.next; 00087 p->alink.next = NULL; 00088 result.push(p); 00089 p = pnext; 00090 } 00091 if (!shouldDestroy()) 00092 continuation->handleEvent(NET_EVENT_DATAGRAM_READ_READY, &result); 00093 else { 00094 while ((p = result.dequeue())) 00095 p->free(); 00096 } 00097 } 00098 } 00099 Release(); 00100 return EVENT_CONT; 00101 } 00102 00103 void 00104 UDPConnection::bindToThread(Continuation * c) 00105 { 00106 UnixUDPConnection *uc = (UnixUDPConnection *) this; 00107 //add to new connections queue for EThread. 00108 EThread *t = eventProcessor.assign_thread(ET_UDP); 00109 ink_assert(t); 00110 ink_assert(get_UDPNetHandler(t)); 00111 uc->ethread = t; 00112 AddRef(); 00113 uc->continuation = c; 00114 mutex = c->mutex; 00115 ink_atomiclist_push(&get_UDPNetHandler(t)->udpNewConnections, uc); 00116 } 00117 00118 Action * 00119 UDPConnection::send(Continuation * c, UDPPacket * xp) 00120 { 00121 UDPPacketInternal *p = (UDPPacketInternal *) xp; 00122 UnixUDPConnection *conn = (UnixUDPConnection *) this; 00123 00124 if (shouldDestroy()) { 00125 ink_assert(!"freeing packet sent on dead connection"); 00126 p->free(); 00127 return ACTION_RESULT_NONE; 00128 } 00129 00130 ink_assert(mutex == c->mutex); 00131 p->setContinuation(c); 00132 p->setConnection(this); 00133 conn->continuation = c; 00134 ink_assert(conn->continuation != NULL); 00135 mutex = c->mutex; 00136 p->reqGenerationNum = conn->sendGenerationNum; 00137 get_UDPNetHandler(conn->ethread)->udpOutQueue.send(p); 00138 return ACTION_RESULT_NONE; 00139 } 00140 00141 void 00142 UDPConnection::Release() 00143 { 00144 UnixUDPConnection *p = (UnixUDPConnection *) this; 00145 00146 p->ep.stop(); 00147 00148 if (ink_atomic_increment(&p->refcount, -1) == 1) { 00149 ink_assert(p->callback_link.next == NULL); 00150 ink_assert(p->callback_link.prev == NULL); 00151 ink_assert(p->polling_link.next == NULL); 00152 ink_assert(p->polling_link.prev == NULL); 00153 ink_assert(p->newconn_alink.next == NULL); 00154 00155 delete this; 00156 } 00157 } 00158