SockInterface.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  1. /** @file
  2. Interface function of the Socket.
  3. Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "SockImpl.h"
  7. /**
  8. Check whether the Event is in the List.
  9. @param[in] List Pointer to the token list to be searched.
  10. @param[in] Event The event to be checked.
  11. @retval TRUE The specific Event exists in the List.
  12. @retval FALSE The specific Event is not in the List.
  13. **/
  14. BOOLEAN
  15. SockTokenExistedInList (
  16. IN LIST_ENTRY *List,
  17. IN EFI_EVENT Event
  18. )
  19. {
  20. LIST_ENTRY *ListEntry;
  21. SOCK_TOKEN *SockToken;
  22. NET_LIST_FOR_EACH (ListEntry, List) {
  23. SockToken = NET_LIST_USER_STRUCT (
  24. ListEntry,
  25. SOCK_TOKEN,
  26. TokenList
  27. );
  28. if (Event == SockToken->Token->Event) {
  29. return TRUE;
  30. }
  31. }
  32. return FALSE;
  33. }
  34. /**
  35. Call SockTokenExistedInList() to check whether the Event is
  36. in the related socket's lists.
  37. @param[in] Sock Pointer to the instance's socket.
  38. @param[in] Event The event to be checked.
  39. @retval TRUE The Event exists in related socket's lists.
  40. @retval FALSE The Event is not in related socket's lists.
  41. **/
  42. BOOLEAN
  43. SockTokenExisted (
  44. IN SOCKET *Sock,
  45. IN EFI_EVENT Event
  46. )
  47. {
  48. if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||
  49. SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||
  50. SockTokenExistedInList (&Sock->RcvTokenList, Event) ||
  51. SockTokenExistedInList (&Sock->ListenTokenList, Event)
  52. )
  53. {
  54. return TRUE;
  55. }
  56. if ((Sock->ConnectionToken != NULL) && (Sock->ConnectionToken->Event == Event)) {
  57. return TRUE;
  58. }
  59. if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {
  60. return TRUE;
  61. }
  62. return FALSE;
  63. }
  64. /**
  65. Buffer a token into the specific list of the socket Sock.
  66. @param[in] Sock Pointer to the instance's socket.
  67. @param[in] List Pointer to the list to store the token.
  68. @param[in] Token Pointer to the token to be buffered.
  69. @param[in] DataLen The data length of the buffer contained in Token.
  70. @return Pointer to the token that wraps Token. If NULL, an error condition occurred.
  71. **/
  72. SOCK_TOKEN *
  73. SockBufferToken (
  74. IN SOCKET *Sock,
  75. IN LIST_ENTRY *List,
  76. IN VOID *Token,
  77. IN UINT32 DataLen
  78. )
  79. {
  80. SOCK_TOKEN *SockToken;
  81. SockToken = AllocateZeroPool (sizeof (SOCK_TOKEN));
  82. if (NULL == SockToken) {
  83. DEBUG (
  84. (DEBUG_ERROR,
  85. "SockBufferIOToken: No Memory to allocate SockToken\n")
  86. );
  87. return NULL;
  88. }
  89. SockToken->Sock = Sock;
  90. SockToken->Token = (SOCK_COMPLETION_TOKEN *)Token;
  91. SockToken->RemainDataLen = DataLen;
  92. InsertTailList (List, &SockToken->TokenList);
  93. return SockToken;
  94. }
  95. /**
  96. Destroy the socket Sock and its associated protocol control block.
  97. @param[in, out] Sock The socket to be destroyed.
  98. @retval EFI_SUCCESS The socket Sock was destroyed successfully.
  99. @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
  100. **/
  101. EFI_STATUS
  102. SockDestroyChild (
  103. IN OUT SOCKET *Sock
  104. )
  105. {
  106. EFI_STATUS Status;
  107. TCP_PROTO_DATA *ProtoData;
  108. TCP_CB *Tcb;
  109. EFI_GUID *IpProtocolGuid;
  110. EFI_GUID *TcpProtocolGuid;
  111. VOID *SockProtocol;
  112. ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL));
  113. if (Sock->InDestroy) {
  114. return EFI_SUCCESS;
  115. }
  116. Sock->InDestroy = TRUE;
  117. if (Sock->IpVersion == IP_VERSION_4) {
  118. IpProtocolGuid = &gEfiIp4ProtocolGuid;
  119. TcpProtocolGuid = &gEfiTcp4ProtocolGuid;
  120. } else {
  121. IpProtocolGuid = &gEfiIp6ProtocolGuid;
  122. TcpProtocolGuid = &gEfiTcp6ProtocolGuid;
  123. }
  124. ProtoData = (TCP_PROTO_DATA *)Sock->ProtoReserved;
  125. Tcb = ProtoData->TcpPcb;
  126. ASSERT (Tcb != NULL);
  127. //
  128. // Close the IP protocol.
  129. //
  130. gBS->CloseProtocol (
  131. Tcb->IpInfo->ChildHandle,
  132. IpProtocolGuid,
  133. ProtoData->TcpService->IpIo->Image,
  134. Sock->SockHandle
  135. );
  136. if (Sock->DestroyCallback != NULL) {
  137. Sock->DestroyCallback (Sock, Sock->Context);
  138. }
  139. //
  140. // Retrieve the protocol installed on this sock
  141. //
  142. Status = gBS->OpenProtocol (
  143. Sock->SockHandle,
  144. TcpProtocolGuid,
  145. &SockProtocol,
  146. Sock->DriverBinding,
  147. Sock->SockHandle,
  148. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  149. );
  150. if (EFI_ERROR (Status)) {
  151. DEBUG (
  152. (DEBUG_ERROR,
  153. "SockDestroyChild: Open protocol installed on socket failed with %r\n",
  154. Status)
  155. );
  156. }
  157. //
  158. // Uninstall the protocol installed on this sock
  159. //
  160. gBS->UninstallMultipleProtocolInterfaces (
  161. Sock->SockHandle,
  162. TcpProtocolGuid,
  163. SockProtocol,
  164. NULL
  165. );
  166. Status = EfiAcquireLockOrFail (&(Sock->Lock));
  167. if (EFI_ERROR (Status)) {
  168. DEBUG (
  169. (DEBUG_ERROR,
  170. "SockDestroyChild: Get the lock to access socket failed with %r\n",
  171. Status)
  172. );
  173. return EFI_ACCESS_DENIED;
  174. }
  175. //
  176. // force protocol layer to detach the PCB
  177. //
  178. Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);
  179. if (EFI_ERROR (Status)) {
  180. DEBUG (
  181. (DEBUG_ERROR,
  182. "SockDestroyChild: Protocol detach socket failed with %r\n",
  183. Status)
  184. );
  185. Sock->InDestroy = FALSE;
  186. } else if (SOCK_IS_CONFIGURED (Sock)) {
  187. SockConnFlush (Sock);
  188. SockSetState (Sock, SO_CLOSED);
  189. Sock->ConfigureState = SO_UNCONFIGURED;
  190. }
  191. EfiReleaseLock (&(Sock->Lock));
  192. if (EFI_ERROR (Status)) {
  193. return Status;
  194. }
  195. SockDestroy (Sock);
  196. return EFI_SUCCESS;
  197. }
  198. /**
  199. Create a socket and its associated protocol control block
  200. with the initial data SockInitData and protocol specific
  201. data ProtoData.
  202. @param[in] SockInitData Initial data to setting the socket.
  203. @return Pointer to the newly created socket. If NULL, an error condition occurred.
  204. **/
  205. SOCKET *
  206. SockCreateChild (
  207. IN SOCK_INIT_DATA *SockInitData
  208. )
  209. {
  210. SOCKET *Sock;
  211. EFI_STATUS Status;
  212. VOID *SockProtocol;
  213. EFI_GUID *TcpProtocolGuid;
  214. //
  215. // create a new socket
  216. //
  217. Sock = SockCreate (SockInitData);
  218. if (NULL == Sock) {
  219. DEBUG (
  220. (DEBUG_ERROR,
  221. "SockCreateChild: No resource to create a new socket\n")
  222. );
  223. return NULL;
  224. }
  225. Status = EfiAcquireLockOrFail (&(Sock->Lock));
  226. if (EFI_ERROR (Status)) {
  227. DEBUG (
  228. (DEBUG_ERROR,
  229. "SockCreateChild: Get the lock to access socket failed with %r\n",
  230. Status)
  231. );
  232. goto ERROR;
  233. }
  234. //
  235. // inform the protocol layer to attach the socket
  236. // with a new protocol control block
  237. //
  238. Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);
  239. EfiReleaseLock (&(Sock->Lock));
  240. if (EFI_ERROR (Status)) {
  241. DEBUG (
  242. (DEBUG_ERROR,
  243. "SockCreateChild: Protocol failed to attach a socket with %r\n",
  244. Status)
  245. );
  246. goto ERROR;
  247. }
  248. return Sock;
  249. ERROR:
  250. if (Sock->DestroyCallback != NULL) {
  251. Sock->DestroyCallback (Sock, Sock->Context);
  252. }
  253. if (Sock->IpVersion == IP_VERSION_4) {
  254. TcpProtocolGuid = &gEfiTcp4ProtocolGuid;
  255. } else {
  256. TcpProtocolGuid = &gEfiTcp6ProtocolGuid;
  257. }
  258. gBS->OpenProtocol (
  259. Sock->SockHandle,
  260. TcpProtocolGuid,
  261. &SockProtocol,
  262. Sock->DriverBinding,
  263. Sock->SockHandle,
  264. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  265. );
  266. //
  267. // Uninstall the protocol installed on this sock
  268. //
  269. gBS->UninstallMultipleProtocolInterfaces (
  270. Sock->SockHandle,
  271. TcpProtocolGuid,
  272. SockProtocol,
  273. NULL
  274. );
  275. SockDestroy (Sock);
  276. return NULL;
  277. }
  278. /**
  279. Configure the specific socket Sock using configuration data ConfigData.
  280. @param[in] Sock Pointer to the socket to be configured.
  281. @param[in] ConfigData Pointer to the configuration data.
  282. @retval EFI_SUCCESS The socket configured successfully.
  283. @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
  284. socket is already configured.
  285. **/
  286. EFI_STATUS
  287. SockConfigure (
  288. IN SOCKET *Sock,
  289. IN VOID *ConfigData
  290. )
  291. {
  292. EFI_STATUS Status;
  293. Status = EfiAcquireLockOrFail (&(Sock->Lock));
  294. if (EFI_ERROR (Status)) {
  295. DEBUG (
  296. (DEBUG_ERROR,
  297. "SockConfigure: Get the access for socket failed with %r",
  298. Status)
  299. );
  300. return EFI_ACCESS_DENIED;
  301. }
  302. if (SOCK_IS_CONFIGURED (Sock)) {
  303. Status = EFI_ACCESS_DENIED;
  304. goto OnExit;
  305. }
  306. ASSERT (Sock->State == SO_CLOSED);
  307. Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);
  308. OnExit:
  309. EfiReleaseLock (&(Sock->Lock));
  310. return Status;
  311. }
  312. /**
  313. Initiate a connection establishment process.
  314. @param[in] Sock Pointer to the socket to initiate the
  315. connection.
  316. @param[in] Token Pointer to the token used for the connection
  317. operation.
  318. @retval EFI_SUCCESS The connection initialized successfully.
  319. @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
  320. socket is closed, or the socket is not configured to
  321. be an active one, or the token is already in one of
  322. this socket's lists.
  323. @retval EFI_NO_MAPPING The IP address configuration operation is not
  324. finished.
  325. @retval EFI_NOT_STARTED The socket is not configured.
  326. **/
  327. EFI_STATUS
  328. SockConnect (
  329. IN SOCKET *Sock,
  330. IN VOID *Token
  331. )
  332. {
  333. EFI_STATUS Status;
  334. EFI_EVENT Event;
  335. Status = EfiAcquireLockOrFail (&(Sock->Lock));
  336. if (EFI_ERROR (Status)) {
  337. DEBUG (
  338. (DEBUG_ERROR,
  339. "SockConnect: Get the access for socket failed with %r",
  340. Status)
  341. );
  342. return EFI_ACCESS_DENIED;
  343. }
  344. if (SOCK_IS_NO_MAPPING (Sock)) {
  345. Status = EFI_NO_MAPPING;
  346. goto OnExit;
  347. }
  348. if (SOCK_IS_UNCONFIGURED (Sock)) {
  349. Status = EFI_NOT_STARTED;
  350. goto OnExit;
  351. }
  352. if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {
  353. Status = EFI_ACCESS_DENIED;
  354. goto OnExit;
  355. }
  356. Event = ((SOCK_COMPLETION_TOKEN *)Token)->Event;
  357. if (SockTokenExisted (Sock, Event)) {
  358. Status = EFI_ACCESS_DENIED;
  359. goto OnExit;
  360. }
  361. Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *)Token;
  362. SockSetState (Sock, SO_CONNECTING);
  363. Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);
  364. OnExit:
  365. EfiReleaseLock (&(Sock->Lock));
  366. return Status;
  367. }
  368. /**
  369. Issue a listen token to get an existed connected network instance
  370. or wait for a connection if there is none.
  371. @param[in] Sock Pointer to the socket to accept connections.
  372. @param[in] Token The token to accept a connection.
  373. @retval EFI_SUCCESS Either a connection is accepted or the Token is
  374. buffered for further acception.
  375. @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
  376. socket is closed, or the socket is not configured to
  377. be a passive one, or the token is already in one of
  378. this socket's lists.
  379. @retval EFI_NO_MAPPING The IP address configuration operation is not
  380. finished.
  381. @retval EFI_NOT_STARTED The socket is not configured.
  382. @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limits.
  383. **/
  384. EFI_STATUS
  385. SockAccept (
  386. IN SOCKET *Sock,
  387. IN VOID *Token
  388. )
  389. {
  390. EFI_TCP4_LISTEN_TOKEN *ListenToken;
  391. LIST_ENTRY *ListEntry;
  392. EFI_STATUS Status;
  393. SOCKET *Socket;
  394. EFI_EVENT Event;
  395. ASSERT (SockStream == Sock->Type);
  396. Status = EfiAcquireLockOrFail (&(Sock->Lock));
  397. if (EFI_ERROR (Status)) {
  398. DEBUG (
  399. (DEBUG_ERROR,
  400. "SockAccept: Get the access for socket failed with %r",
  401. Status)
  402. );
  403. return EFI_ACCESS_DENIED;
  404. }
  405. if (SOCK_IS_NO_MAPPING (Sock)) {
  406. Status = EFI_NO_MAPPING;
  407. goto Exit;
  408. }
  409. if (SOCK_IS_UNCONFIGURED (Sock)) {
  410. Status = EFI_NOT_STARTED;
  411. goto Exit;
  412. }
  413. if (!SOCK_IS_LISTENING (Sock)) {
  414. Status = EFI_ACCESS_DENIED;
  415. goto Exit;
  416. }
  417. Event = ((SOCK_COMPLETION_TOKEN *)Token)->Event;
  418. if (SockTokenExisted (Sock, Event)) {
  419. Status = EFI_ACCESS_DENIED;
  420. goto Exit;
  421. }
  422. ListenToken = (EFI_TCP4_LISTEN_TOKEN *)Token;
  423. //
  424. // Check if a connection has already in this Sock->ConnectionList
  425. //
  426. NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {
  427. Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);
  428. if (SOCK_IS_CONNECTED (Socket)) {
  429. ListenToken->NewChildHandle = Socket->SockHandle;
  430. SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);
  431. RemoveEntryList (ListEntry);
  432. ASSERT (Socket->Parent != NULL);
  433. Socket->Parent->ConnCnt--;
  434. DEBUG (
  435. (DEBUG_NET,
  436. "SockAccept: Accept a socket, now conncount is %d",
  437. Socket->Parent->ConnCnt)
  438. );
  439. Socket->Parent = NULL;
  440. goto Exit;
  441. }
  442. }
  443. //
  444. // Buffer this token for latter incoming connection request
  445. //
  446. if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {
  447. Status = EFI_OUT_OF_RESOURCES;
  448. }
  449. Exit:
  450. EfiReleaseLock (&(Sock->Lock));
  451. return Status;
  452. }
  453. /**
  454. Issue a token with data to the socket to send out.
  455. @param[in] Sock Pointer to the socket to process the token with
  456. data.
  457. @param[in] Token The token with data that needs to send out.
  458. @retval EFI_SUCCESS The token processed successfully.
  459. @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
  460. socket is closed, or the socket is not in a
  461. synchronized state , or the token is already in one
  462. of this socket's lists.
  463. @retval EFI_NO_MAPPING The IP address configuration operation is not
  464. finished.
  465. @retval EFI_NOT_STARTED The socket is not configured.
  466. @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limits.
  467. **/
  468. EFI_STATUS
  469. SockSend (
  470. IN SOCKET *Sock,
  471. IN VOID *Token
  472. )
  473. {
  474. SOCK_IO_TOKEN *SndToken;
  475. EFI_EVENT Event;
  476. UINT32 FreeSpace;
  477. EFI_TCP4_TRANSMIT_DATA *TxData;
  478. EFI_STATUS Status;
  479. SOCK_TOKEN *SockToken;
  480. UINT32 DataLen;
  481. ASSERT (SockStream == Sock->Type);
  482. Status = EfiAcquireLockOrFail (&(Sock->Lock));
  483. if (EFI_ERROR (Status)) {
  484. DEBUG (
  485. (DEBUG_ERROR,
  486. "SockSend: Get the access for socket failed with %r",
  487. Status)
  488. );
  489. return EFI_ACCESS_DENIED;
  490. }
  491. if (SOCK_IS_NO_MAPPING (Sock)) {
  492. Status = EFI_NO_MAPPING;
  493. goto Exit;
  494. }
  495. SndToken = (SOCK_IO_TOKEN *)Token;
  496. TxData = (EFI_TCP4_TRANSMIT_DATA *)SndToken->Packet.TxData;
  497. if (SOCK_IS_UNCONFIGURED (Sock)) {
  498. Status = EFI_NOT_STARTED;
  499. goto Exit;
  500. }
  501. if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {
  502. Status = EFI_ACCESS_DENIED;
  503. goto Exit;
  504. }
  505. //
  506. // check if a token is already in the token buffer
  507. //
  508. Event = SndToken->Token.Event;
  509. if (SockTokenExisted (Sock, Event)) {
  510. Status = EFI_ACCESS_DENIED;
  511. goto Exit;
  512. }
  513. DataLen = TxData->DataLength;
  514. //
  515. // process this sending token now or buffer it only?
  516. //
  517. FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);
  518. if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {
  519. SockToken = SockBufferToken (
  520. Sock,
  521. &Sock->SndTokenList,
  522. SndToken,
  523. DataLen
  524. );
  525. if (NULL == SockToken) {
  526. Status = EFI_OUT_OF_RESOURCES;
  527. }
  528. } else {
  529. SockToken = SockBufferToken (
  530. Sock,
  531. &Sock->ProcessingSndTokenList,
  532. SndToken,
  533. DataLen
  534. );
  535. if (NULL == SockToken) {
  536. DEBUG ((DEBUG_ERROR, "SockSend: Failed to buffer IO token into socket processing SndToken List\n"));
  537. Status = EFI_OUT_OF_RESOURCES;
  538. goto Exit;
  539. }
  540. Status = SockProcessTcpSndData (Sock, TxData);
  541. if (EFI_ERROR (Status)) {
  542. DEBUG ((DEBUG_ERROR, "SockSend: Failed to process Snd Data\n"));
  543. RemoveEntryList (&(SockToken->TokenList));
  544. FreePool (SockToken);
  545. }
  546. }
  547. Exit:
  548. EfiReleaseLock (&(Sock->Lock));
  549. return Status;
  550. }
  551. /**
  552. Issue a token to get data from the socket.
  553. @param[in] Sock Pointer to the socket to get data from.
  554. @param[in] Token The token to store the received data from the
  555. socket.
  556. @retval EFI_SUCCESS The token processed successfully.
  557. @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
  558. socket is closed, or the socket is not in a
  559. synchronized state , or the token is already in one
  560. of this socket's lists.
  561. @retval EFI_NO_MAPPING The IP address configuration operation is not
  562. finished.
  563. @retval EFI_NOT_STARTED The socket is not configured.
  564. @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
  565. @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
  566. **/
  567. EFI_STATUS
  568. SockRcv (
  569. IN SOCKET *Sock,
  570. IN VOID *Token
  571. )
  572. {
  573. SOCK_IO_TOKEN *RcvToken;
  574. UINT32 RcvdBytes;
  575. EFI_STATUS Status;
  576. EFI_EVENT Event;
  577. ASSERT (SockStream == Sock->Type);
  578. Status = EfiAcquireLockOrFail (&(Sock->Lock));
  579. if (EFI_ERROR (Status)) {
  580. DEBUG (
  581. (DEBUG_ERROR,
  582. "SockRcv: Get the access for socket failed with %r",
  583. Status)
  584. );
  585. return EFI_ACCESS_DENIED;
  586. }
  587. if (SOCK_IS_NO_MAPPING (Sock)) {
  588. Status = EFI_NO_MAPPING;
  589. goto Exit;
  590. }
  591. if (SOCK_IS_UNCONFIGURED (Sock)) {
  592. Status = EFI_NOT_STARTED;
  593. goto Exit;
  594. }
  595. if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {
  596. Status = EFI_ACCESS_DENIED;
  597. goto Exit;
  598. }
  599. RcvToken = (SOCK_IO_TOKEN *)Token;
  600. //
  601. // check if a token is already in the token buffer of this socket
  602. //
  603. Event = RcvToken->Token.Event;
  604. if (SockTokenExisted (Sock, Event)) {
  605. Status = EFI_ACCESS_DENIED;
  606. goto Exit;
  607. }
  608. RcvToken = (SOCK_IO_TOKEN *)Token;
  609. RcvdBytes = GET_RCV_DATASIZE (Sock);
  610. //
  611. // check whether an error has happened before
  612. //
  613. if (EFI_ABORTED != Sock->SockError) {
  614. SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);
  615. Sock->SockError = EFI_ABORTED;
  616. goto Exit;
  617. }
  618. //
  619. // check whether can not receive and there is no any
  620. // data buffered in Sock->RcvBuffer
  621. //
  622. if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {
  623. Status = EFI_CONNECTION_FIN;
  624. goto Exit;
  625. }
  626. if (RcvdBytes != 0) {
  627. SockProcessRcvToken (Sock, RcvToken);
  628. Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);
  629. } else {
  630. if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {
  631. Status = EFI_OUT_OF_RESOURCES;
  632. }
  633. }
  634. Exit:
  635. EfiReleaseLock (&(Sock->Lock));
  636. return Status;
  637. }
  638. /**
  639. Reset the socket and its associated protocol control block.
  640. @param[in, out] Sock Pointer to the socket to be flushed.
  641. @retval EFI_SUCCESS The socket is flushed successfully.
  642. @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
  643. **/
  644. EFI_STATUS
  645. SockFlush (
  646. IN OUT SOCKET *Sock
  647. )
  648. {
  649. EFI_STATUS Status;
  650. ASSERT (SockStream == Sock->Type);
  651. Status = EfiAcquireLockOrFail (&(Sock->Lock));
  652. if (EFI_ERROR (Status)) {
  653. DEBUG (
  654. (DEBUG_ERROR,
  655. "SockFlush: Get the access for socket failed with %r",
  656. Status)
  657. );
  658. return EFI_ACCESS_DENIED;
  659. }
  660. if (!SOCK_IS_CONFIGURED (Sock)) {
  661. Status = EFI_ACCESS_DENIED;
  662. goto Exit;
  663. }
  664. Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);
  665. if (EFI_ERROR (Status)) {
  666. DEBUG (
  667. (DEBUG_ERROR,
  668. "SockFlush: Protocol failed handling SOCK_FLUSH with %r",
  669. Status)
  670. );
  671. goto Exit;
  672. }
  673. SOCK_ERROR (Sock, EFI_ABORTED);
  674. SockConnFlush (Sock);
  675. SockSetState (Sock, SO_CLOSED);
  676. Sock->ConfigureState = SO_UNCONFIGURED;
  677. Exit:
  678. EfiReleaseLock (&(Sock->Lock));
  679. return Status;
  680. }
  681. /**
  682. Close or abort the socket associated connection.
  683. @param[in, out] Sock Pointer to the socket of the connection to close
  684. or abort.
  685. @param[in] Token The token for a close operation.
  686. @param[in] OnAbort TRUE for aborting the connection; FALSE to close it.
  687. @retval EFI_SUCCESS The close or abort operation initialized
  688. successfully.
  689. @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
  690. socket is closed, or the socket is not in a
  691. synchronized state , or the token is already in one
  692. of this socket's lists.
  693. @retval EFI_NO_MAPPING The IP address configuration operation is not
  694. finished.
  695. @retval EFI_NOT_STARTED The socket is not configured.
  696. **/
  697. EFI_STATUS
  698. SockClose (
  699. IN OUT SOCKET *Sock,
  700. IN VOID *Token,
  701. IN BOOLEAN OnAbort
  702. )
  703. {
  704. EFI_STATUS Status;
  705. EFI_EVENT Event;
  706. ASSERT (SockStream == Sock->Type);
  707. Status = EfiAcquireLockOrFail (&(Sock->Lock));
  708. if (EFI_ERROR (Status)) {
  709. DEBUG (
  710. (DEBUG_ERROR,
  711. "SockClose: Get the access for socket failed with %r",
  712. Status)
  713. );
  714. return EFI_ACCESS_DENIED;
  715. }
  716. if (SOCK_IS_NO_MAPPING (Sock)) {
  717. Status = EFI_NO_MAPPING;
  718. goto Exit;
  719. }
  720. if (SOCK_IS_UNCONFIGURED (Sock)) {
  721. Status = EFI_NOT_STARTED;
  722. goto Exit;
  723. }
  724. if (SOCK_IS_DISCONNECTING (Sock)) {
  725. Status = EFI_ACCESS_DENIED;
  726. goto Exit;
  727. }
  728. Event = ((SOCK_COMPLETION_TOKEN *)Token)->Event;
  729. if (SockTokenExisted (Sock, Event)) {
  730. Status = EFI_ACCESS_DENIED;
  731. goto Exit;
  732. }
  733. Sock->CloseToken = Token;
  734. SockSetState (Sock, SO_DISCONNECTING);
  735. if (OnAbort) {
  736. Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);
  737. } else {
  738. Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);
  739. }
  740. Exit:
  741. EfiReleaseLock (&(Sock->Lock));
  742. return Status;
  743. }
  744. /**
  745. Abort the socket associated connection, listen, transmission or receive request.
  746. @param[in, out] Sock Pointer to the socket to abort.
  747. @param[in] Token Pointer to a token that has been issued by
  748. Connect(), Accept(), Transmit() or Receive(). If
  749. NULL, all pending tokens issued by the four
  750. functions listed above will be aborted.
  751. @retval EFI_UNSUPPORTED The operation is not supported in the current
  752. implementation.
  753. **/
  754. EFI_STATUS
  755. SockCancel (
  756. IN OUT SOCKET *Sock,
  757. IN VOID *Token
  758. )
  759. {
  760. EFI_STATUS Status;
  761. Status = EFI_SUCCESS;
  762. ASSERT (SockStream == Sock->Type);
  763. Status = EfiAcquireLockOrFail (&(Sock->Lock));
  764. if (EFI_ERROR (Status)) {
  765. DEBUG (
  766. (DEBUG_ERROR,
  767. "SockCancel: Get the access for socket failed with %r",
  768. Status)
  769. );
  770. return EFI_ACCESS_DENIED;
  771. }
  772. if (SOCK_IS_UNCONFIGURED (Sock)) {
  773. Status = EFI_NOT_STARTED;
  774. goto Exit;
  775. }
  776. //
  777. // 1. Check ConnectionToken.
  778. //
  779. if ((Token == NULL) || ((SOCK_COMPLETION_TOKEN *)Token == Sock->ConnectionToken)) {
  780. if (Sock->ConnectionToken != NULL) {
  781. SIGNAL_TOKEN (Sock->ConnectionToken, EFI_ABORTED);
  782. Sock->ConnectionToken = NULL;
  783. }
  784. if (Token != NULL) {
  785. Status = EFI_SUCCESS;
  786. goto Exit;
  787. }
  788. }
  789. //
  790. // 2. Check ListenTokenList.
  791. //
  792. Status = SockCancelToken (Token, &Sock->ListenTokenList);
  793. if ((Token != NULL) && !EFI_ERROR (Status)) {
  794. goto Exit;
  795. }
  796. //
  797. // 3. Check RcvTokenList.
  798. //
  799. Status = SockCancelToken (Token, &Sock->RcvTokenList);
  800. if ((Token != NULL) && !EFI_ERROR (Status)) {
  801. goto Exit;
  802. }
  803. //
  804. // 4. Check SndTokenList.
  805. //
  806. Status = SockCancelToken (Token, &Sock->SndTokenList);
  807. if ((Token != NULL) && !EFI_ERROR (Status)) {
  808. goto Exit;
  809. }
  810. //
  811. // 5. Check ProcessingSndTokenList.
  812. //
  813. Status = SockCancelToken (Token, &Sock->ProcessingSndTokenList);
  814. Exit:
  815. EfiReleaseLock (&(Sock->Lock));
  816. return Status;
  817. }
  818. /**
  819. Get the mode data of the low layer protocol.
  820. @param[in] Sock Pointer to the socket to get mode data from.
  821. @param[in, out] Mode Pointer to the data to store the low layer mode
  822. information.
  823. @retval EFI_SUCCESS The mode data was obtained successfully.
  824. @retval EFI_NOT_STARTED The socket is not configured.
  825. **/
  826. EFI_STATUS
  827. SockGetMode (
  828. IN SOCKET *Sock,
  829. IN OUT VOID *Mode
  830. )
  831. {
  832. return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);
  833. }
  834. /**
  835. Add or remove route information in IP route table associated
  836. with this socket.
  837. @param[in] Sock Pointer to the socket associated with the IP route
  838. table to operate on.
  839. @param[in] RouteInfo Pointer to the route information to be processed.
  840. @retval EFI_SUCCESS The route table updated successfully.
  841. @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
  842. @retval EFI_NO_MAPPING The IP address configuration operation is not
  843. finished.
  844. @retval EFI_NOT_STARTED The socket is not configured.
  845. **/
  846. EFI_STATUS
  847. SockRoute (
  848. IN SOCKET *Sock,
  849. IN VOID *RouteInfo
  850. )
  851. {
  852. EFI_STATUS Status;
  853. Status = EfiAcquireLockOrFail (&(Sock->Lock));
  854. if (EFI_ERROR (Status)) {
  855. DEBUG (
  856. (DEBUG_ERROR,
  857. "SockRoute: Get the access for socket failed with %r",
  858. Status)
  859. );
  860. return EFI_ACCESS_DENIED;
  861. }
  862. if (SOCK_IS_NO_MAPPING (Sock)) {
  863. Status = EFI_NO_MAPPING;
  864. goto Exit;
  865. }
  866. if (SOCK_IS_UNCONFIGURED (Sock)) {
  867. Status = EFI_NOT_STARTED;
  868. goto Exit;
  869. }
  870. Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);
  871. Exit:
  872. EfiReleaseLock (&(Sock->Lock));
  873. return Status;
  874. }