1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18
19 #include "osclconfig_io.h"
20 #include "oscl_scheduler_ao.h"
21 #include "oscl_socket_method.h"
22 #include "oscl_socket_imp.h"
23 #include "oscl_assert.h"
24
25
26 static const char* const TPVSocketFxnStr[] =
27 {
28 "EPVSocketSend"
29 , "EPVSocketSendTo"
30 , "EPVSocketRecv"
31 , "EPVSocketRecvFrom"
32 , "EPVSocketConnect"
33 , "EPVSocketAccept"
34 , "EPVSocketShutdown"
35 , "EPVSocketBindUdp"
36 , "EPVSocketBindTcp"
37 , "EPVSocketListen"
38 } ;
39 static const char* const TPVSocketEventStr[] =
40 {
41 "EPVSocketSuccess"
42 , "EPVSocketPending"
43 , "EPVSocketTimeout"
44 , "EPVSocketFailure"
45 , "EPVSocketCancel"
46 };
47
48 /** OsclSocketRequestAO is the base class for all the AOs that
49 interact directly with the socket server. This object
50 is contained within an OsclSocketMethod object
51 */
52
GetSocketError()53 inline int OsclSocketRequestAO::GetSocketError()
54 {
55 #if (PV_SOCKET_SERVER)
56
57 //Errors from PV socket server are in
58 //iSocketError.
59 return iSocketError;
60
61 #else
62
63 #error No Implementation!
64
65 #endif
66 }
67
68 //Stats macros for use with OsclSocketRequestAO
69 #if(PV_OSCL_SOCKET_STATS_LOGGING)
70 #define ADD_STATS(a,b) SocketI()->iStats.Add(a,b)
71 #define LOG_STATS(a) SocketI()->iStats.Log(a)
72 #define CLEAR_STATS(a) SocketI()->iStats.Clear(a)
73 #else
74 #define ADD_STATS(a,b)
75 #define LOG_STATS(a)
76 #define CLEAR_STATS(a)
77 #endif
78
79 #define LOGINFOMED(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG,iContainer.iContainer.iLogger,PVLOGMSG_DEBUG,m);
80
Run()81 void OsclSocketRequestAO::Run()
82 {
83 //The server has completed the socket request.
84
85 RequestDone();
86
87
88 // Check the request completion status
89 switch (Status())
90 {
91 case OSCL_REQUEST_ERR_NONE:
92 ADD_STATS(iContainer.iSocketFxn, EOsclSocket_RequestAO_Success);
93 Success();
94 LOGINFOMED((0, "OsclSocket(0x%x): %s %s ", SocketI(), TPVSocketFxnStr[iContainer.iSocketFxn], TPVSocketEventStr[EPVSocketSuccess]));
95 LOG_STATS(iContainer.iSocketFxn);
96 CLEAR_STATS(iContainer.iSocketFxn);
97 SocketObserver()->HandleSocketEvent(Id(), iContainer.iSocketFxn, EPVSocketSuccess, 0);
98 break;
99
100 case OSCL_REQUEST_ERR_CANCEL:
101 ADD_STATS(iContainer.iSocketFxn, EOsclSocket_RequestAO_Canceled);
102 //Request was cancelled, either due to an API call or due to the
103 //socket server shutting down before completing the operation.
104 LOGINFOMED((0, "OsclSocket(0x%x): %s %s ", SocketI(), TPVSocketFxnStr[iContainer.iSocketFxn], TPVSocketEventStr[EPVSocketCancel]));
105 LOG_STATS(iContainer.iSocketFxn);
106 CLEAR_STATS(iContainer.iSocketFxn);
107 SocketObserver()->HandleSocketEvent(Id(), iContainer.iSocketFxn, EPVSocketCancel, 0);
108 break;
109
110 default:
111 ADD_STATS(iContainer.iSocketFxn, EOsclSocket_RequestAO_Error);
112 //Some error.
113 LOGINFOMED((0, "OsclSocket(0x%x): %s %s %d", SocketI(), TPVSocketFxnStr[iContainer.iSocketFxn], TPVSocketEventStr[EPVSocketFailure], GetSocketError()));
114 LOG_STATS(iContainer.iSocketFxn);
115 CLEAR_STATS(iContainer.iSocketFxn);
116 SocketObserver()->HandleSocketEvent(Id(), iContainer.iSocketFxn, EPVSocketFailure, GetSocketError());
117 break;
118 }
119 }
120
NewRequest(const uint32 size)121 OsclAny* OsclSocketRequestAO::NewRequest(const uint32 size)
122 {
123 //Activate the AO. The socket server will complete the request.
124 PendForExec();
125
126 bool reallocate = (!iParam || size != iParamSize);
127
128 //Cleanup any previous parameters.
129 CleanupParam(reallocate);
130
131 LOGINFOMED((0, "OsclSocket(0x%x): New Request %s", SocketI(), TPVSocketFxnStr[iContainer.iSocketFxn]));
132
133 //Allocate space for new parameters, or recycle current space.
134 if (reallocate)
135 {
136 iParamSize = size;
137 return Alloc().ALLOCATE(size);
138 }
139 else
140 return iParam;
141 }
142
CleanupParam(bool aDeallocate)143 void OsclSocketRequestAO::CleanupParam(bool aDeallocate)
144 {
145 //cleanup the socket request parameters-- can't use
146 //virtual destructor because an allocator was used and
147 //destructor is called explicitly.
148 if (iParam)
149 {
150 switch (iContainer.iSocketFxn)
151 {
152 case EPVSocketRecvFrom:
153 ((RecvFromParam*)iParam)->~RecvFromParam();
154 break;
155 case EPVSocketRecv:
156 ((RecvParam*)iParam)->~RecvParam();
157 break;
158 case EPVSocketSendTo:
159 ((SendToParam*)iParam)->~SendToParam();
160 break;
161 case EPVSocketSend:
162 ((SendParam*)iParam)->~SendParam();
163 break;
164 case EPVSocketAccept:
165 ((AcceptParam*)iParam)->~AcceptParam();
166 break;
167 case EPVSocketConnect:
168 ((ConnectParam*)iParam)->~ConnectParam();
169 break;
170 case EPVSocketShutdown:
171 ((ShutdownParam*)iParam)->~ShutdownParam();
172 break;
173 case EPVSocketBind:
174 ((BindParam*)iParam)->~BindParam();
175 break;
176 case EPVSocketListen:
177 ((ListenParam*)iParam)->~ListenParam();
178 break;
179 default:
180 OSCL_ASSERT(false);
181 break;
182 }
183 //free memory if needed.
184 if (aDeallocate)
185 {
186 Alloc().deallocate(iParam);
187 iParam = NULL;
188 iParamSize = 0;
189 }
190 }
191 }
192
193
194 /** OsclSocketMethod is the base class for all the AOs that
195 implement asynchronous socket requests. It implements the timeout.
196 */
197
StartMethod(int32 aTimeoutMsec)198 bool OsclSocketMethod::StartMethod(int32 aTimeoutMsec)
199 {
200 //make sure there's not already a request
201 //in progress
202 if (iSocketRequestAO->IsBusy()
203 || IsBusy())
204 return false;
205
206 if (!iSocketRequestAO->IsAdded())
207 iSocketRequestAO->AddToScheduler();
208
209 //set the timeout if any. Timeout <= 0 indicates infinite wait.
210 if (aTimeoutMsec > 0)
211 {
212 if (!IsAdded())
213 AddToScheduler();
214 After(aTimeoutMsec*MSEC_TO_MICROSEC);
215 }
216
217 iSocketRequestAO->iSocketError = 0;
218
219 return true;
220 }
221
222 //Stats macros for use with OsclSocketMethod
223 #undef ADD_STATS
224 #undef LOG_STATS
225 #undef CLEAR_STATS
226 #if(PV_OSCL_SOCKET_STATS_LOGGING)
227 #define ADD_STATS(a,b) iSocketRequestAO->SocketI()->iStats.Add(a,b)
228 #define LOG_STATS(a) iSocketRequestAO->SocketI()->iStats.Log(a)
229 #define CLEAR_STATS(a) iSocketRequestAO->SocketI()->iStats.Clear(a)
230 #else
231 #define ADD_STATS(a,b)
232 #define LOG_STATS(a)
233 #define CLEAR_STATS(a)
234 #endif
235
Run()236 void OsclSocketMethod::Run()
237 {
238 ADD_STATS(iSocketFxn, EOsclSocket_RequestAO_Timeout);
239 //The socket request has timed out.
240 MethodDone();
241 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iContainer.iLogger, PVLOGMSG_DEBUG
242 , (0, "OsclSocket: %s %s ", TPVSocketFxnStr[iSocketFxn], TPVSocketEventStr[EPVSocketTimeout]));
243 LOG_STATS(iSocketFxn);
244 CLEAR_STATS(iSocketFxn);
245 iContainer.iObserver->HandleSocketEvent(iContainer.iId, iSocketFxn, EPVSocketTimeout, 0);
246 }
247
248
249