sockets.c 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2016 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Chris Vandomelen <chrisv@b0rked.dhs.org> |
  16. | Sterling Hughes <sterling@php.net> |
  17. | Jason Greene <jason@php.net> |
  18. | Gustavo Lopes <cataphract@php.net> |
  19. | WinSock: Daniel Beulshausen <daniel@php4win.de> |
  20. +----------------------------------------------------------------------+
  21. */
  22. /* $Id$ */
  23. #ifdef HAVE_CONFIG_H
  24. #include "config.h"
  25. #endif
  26. #include "php.h"
  27. #include "php_network.h"
  28. #include "ext/standard/file.h"
  29. #include "ext/standard/info.h"
  30. #include "php_ini.h"
  31. #ifdef PHP_WIN32
  32. # include "windows_common.h"
  33. # include <win32/inet.h>
  34. # include <windows.h>
  35. # include <Ws2tcpip.h>
  36. # include "php_sockets.h"
  37. # include <win32/sockets.h>
  38. #else
  39. # include <sys/types.h>
  40. # include <sys/socket.h>
  41. # include <netdb.h>
  42. # include <netinet/in.h>
  43. # include <netinet/tcp.h>
  44. # include <sys/un.h>
  45. # include <arpa/inet.h>
  46. # include <sys/time.h>
  47. # include <unistd.h>
  48. # include <errno.h>
  49. # include <fcntl.h>
  50. # include <signal.h>
  51. # include <sys/uio.h>
  52. # define IS_INVALID_SOCKET(a) (a->bsd_socket < 0)
  53. # define set_errno(a) (errno = a)
  54. # include "php_sockets.h"
  55. # if HAVE_IF_NAMETOINDEX
  56. # include <net/if.h>
  57. # endif
  58. #endif
  59. #include <stddef.h>
  60. #include "sockaddr_conv.h"
  61. #include "multicast.h"
  62. #include "sendrecvmsg.h"
  63. ZEND_DECLARE_MODULE_GLOBALS(sockets)
  64. #ifndef MSG_WAITALL
  65. #ifdef LINUX
  66. #define MSG_WAITALL 0x00000100
  67. #else
  68. #define MSG_WAITALL 0x00000000
  69. #endif
  70. #endif
  71. #ifndef MSG_EOF
  72. #ifdef MSG_FIN
  73. #define MSG_EOF MSG_FIN
  74. #endif
  75. #endif
  76. #ifndef SUN_LEN
  77. #define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
  78. #endif
  79. #ifndef PF_INET
  80. #define PF_INET AF_INET
  81. #endif
  82. #define PHP_NORMAL_READ 0x0001
  83. #define PHP_BINARY_READ 0x0002
  84. static int le_socket;
  85. #define le_socket_name php_sockets_le_socket_name
  86. /* {{{ arginfo */
  87. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_select, 0, 0, 4)
  88. ZEND_ARG_INFO(1, read_fds)
  89. ZEND_ARG_INFO(1, write_fds)
  90. ZEND_ARG_INFO(1, except_fds)
  91. ZEND_ARG_INFO(0, tv_sec)
  92. ZEND_ARG_INFO(0, tv_usec)
  93. ZEND_END_ARG_INFO()
  94. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create_listen, 0, 0, 1)
  95. ZEND_ARG_INFO(0, port)
  96. ZEND_ARG_INFO(0, backlog)
  97. ZEND_END_ARG_INFO()
  98. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_accept, 0, 0, 1)
  99. ZEND_ARG_INFO(0, socket)
  100. ZEND_END_ARG_INFO()
  101. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_nonblock, 0, 0, 1)
  102. ZEND_ARG_INFO(0, socket)
  103. ZEND_END_ARG_INFO()
  104. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_block, 0, 0, 1)
  105. ZEND_ARG_INFO(0, socket)
  106. ZEND_END_ARG_INFO()
  107. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_listen, 0, 0, 1)
  108. ZEND_ARG_INFO(0, socket)
  109. ZEND_ARG_INFO(0, backlog)
  110. ZEND_END_ARG_INFO()
  111. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_close, 0, 0, 1)
  112. ZEND_ARG_INFO(0, socket)
  113. ZEND_END_ARG_INFO()
  114. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_write, 0, 0, 2)
  115. ZEND_ARG_INFO(0, socket)
  116. ZEND_ARG_INFO(0, buf)
  117. ZEND_ARG_INFO(0, length)
  118. ZEND_END_ARG_INFO()
  119. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_read, 0, 0, 2)
  120. ZEND_ARG_INFO(0, socket)
  121. ZEND_ARG_INFO(0, length)
  122. ZEND_ARG_INFO(0, type)
  123. ZEND_END_ARG_INFO()
  124. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_getsockname, 0, 0, 2)
  125. ZEND_ARG_INFO(0, socket)
  126. ZEND_ARG_INFO(1, addr)
  127. ZEND_ARG_INFO(1, port)
  128. ZEND_END_ARG_INFO()
  129. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_getpeername, 0, 0, 2)
  130. ZEND_ARG_INFO(0, socket)
  131. ZEND_ARG_INFO(1, addr)
  132. ZEND_ARG_INFO(1, port)
  133. ZEND_END_ARG_INFO()
  134. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create, 0, 0, 3)
  135. ZEND_ARG_INFO(0, domain)
  136. ZEND_ARG_INFO(0, type)
  137. ZEND_ARG_INFO(0, protocol)
  138. ZEND_END_ARG_INFO()
  139. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_connect, 0, 0, 2)
  140. ZEND_ARG_INFO(0, socket)
  141. ZEND_ARG_INFO(0, addr)
  142. ZEND_ARG_INFO(0, port)
  143. ZEND_END_ARG_INFO()
  144. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_strerror, 0, 0, 1)
  145. ZEND_ARG_INFO(0, errno)
  146. ZEND_END_ARG_INFO()
  147. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_bind, 0, 0, 2)
  148. ZEND_ARG_INFO(0, socket)
  149. ZEND_ARG_INFO(0, addr)
  150. ZEND_ARG_INFO(0, port)
  151. ZEND_END_ARG_INFO()
  152. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_recv, 0, 0, 4)
  153. ZEND_ARG_INFO(0, socket)
  154. ZEND_ARG_INFO(1, buf)
  155. ZEND_ARG_INFO(0, len)
  156. ZEND_ARG_INFO(0, flags)
  157. ZEND_END_ARG_INFO()
  158. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_send, 0, 0, 4)
  159. ZEND_ARG_INFO(0, socket)
  160. ZEND_ARG_INFO(0, buf)
  161. ZEND_ARG_INFO(0, len)
  162. ZEND_ARG_INFO(0, flags)
  163. ZEND_END_ARG_INFO()
  164. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_recvfrom, 0, 0, 5)
  165. ZEND_ARG_INFO(0, socket)
  166. ZEND_ARG_INFO(1, buf)
  167. ZEND_ARG_INFO(0, len)
  168. ZEND_ARG_INFO(0, flags)
  169. ZEND_ARG_INFO(1, name)
  170. ZEND_ARG_INFO(1, port)
  171. ZEND_END_ARG_INFO()
  172. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_sendto, 0, 0, 5)
  173. ZEND_ARG_INFO(0, socket)
  174. ZEND_ARG_INFO(0, buf)
  175. ZEND_ARG_INFO(0, len)
  176. ZEND_ARG_INFO(0, flags)
  177. ZEND_ARG_INFO(0, addr)
  178. ZEND_ARG_INFO(0, port)
  179. ZEND_END_ARG_INFO()
  180. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_get_option, 0, 0, 3)
  181. ZEND_ARG_INFO(0, socket)
  182. ZEND_ARG_INFO(0, level)
  183. ZEND_ARG_INFO(0, optname)
  184. ZEND_END_ARG_INFO()
  185. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_option, 0, 0, 4)
  186. ZEND_ARG_INFO(0, socket)
  187. ZEND_ARG_INFO(0, level)
  188. ZEND_ARG_INFO(0, optname)
  189. ZEND_ARG_INFO(0, optval)
  190. ZEND_END_ARG_INFO()
  191. #ifdef HAVE_SOCKETPAIR
  192. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create_pair, 0, 0, 4)
  193. ZEND_ARG_INFO(0, domain)
  194. ZEND_ARG_INFO(0, type)
  195. ZEND_ARG_INFO(0, protocol)
  196. ZEND_ARG_INFO(1, fd)
  197. ZEND_END_ARG_INFO()
  198. #endif
  199. #ifdef HAVE_SHUTDOWN
  200. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_shutdown, 0, 0, 1)
  201. ZEND_ARG_INFO(0, socket)
  202. ZEND_ARG_INFO(0, how)
  203. ZEND_END_ARG_INFO()
  204. #endif
  205. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_last_error, 0, 0, 0)
  206. ZEND_ARG_INFO(0, socket)
  207. ZEND_END_ARG_INFO()
  208. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_clear_error, 0, 0, 0)
  209. ZEND_ARG_INFO(0, socket)
  210. ZEND_END_ARG_INFO()
  211. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_import_stream, 0, 0, 1)
  212. ZEND_ARG_INFO(0, stream)
  213. ZEND_END_ARG_INFO()
  214. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_sendmsg, 0, 0, 3)
  215. ZEND_ARG_INFO(0, socket)
  216. ZEND_ARG_INFO(0, msghdr)
  217. ZEND_ARG_INFO(0, flags)
  218. ZEND_END_ARG_INFO()
  219. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_recvmsg, 0, 0, 3)
  220. ZEND_ARG_INFO(0, socket)
  221. ZEND_ARG_INFO(1, msghdr)
  222. ZEND_ARG_INFO(0, flags)
  223. ZEND_END_ARG_INFO()
  224. ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_cmsg_space, 0, 0, 2)
  225. ZEND_ARG_INFO(0, level)
  226. ZEND_ARG_INFO(0, type)
  227. ZEND_END_ARG_INFO()
  228. /* }}} */
  229. static PHP_GINIT_FUNCTION(sockets);
  230. static PHP_MINIT_FUNCTION(sockets);
  231. static PHP_MSHUTDOWN_FUNCTION(sockets);
  232. static PHP_MINFO_FUNCTION(sockets);
  233. static PHP_RSHUTDOWN_FUNCTION(sockets);
  234. PHP_FUNCTION(socket_select);
  235. PHP_FUNCTION(socket_create_listen);
  236. #ifdef HAVE_SOCKETPAIR
  237. PHP_FUNCTION(socket_create_pair);
  238. #endif
  239. PHP_FUNCTION(socket_accept);
  240. PHP_FUNCTION(socket_set_nonblock);
  241. PHP_FUNCTION(socket_set_block);
  242. PHP_FUNCTION(socket_listen);
  243. PHP_FUNCTION(socket_close);
  244. PHP_FUNCTION(socket_write);
  245. PHP_FUNCTION(socket_read);
  246. PHP_FUNCTION(socket_getsockname);
  247. PHP_FUNCTION(socket_getpeername);
  248. PHP_FUNCTION(socket_create);
  249. PHP_FUNCTION(socket_connect);
  250. PHP_FUNCTION(socket_strerror);
  251. PHP_FUNCTION(socket_bind);
  252. PHP_FUNCTION(socket_recv);
  253. PHP_FUNCTION(socket_send);
  254. PHP_FUNCTION(socket_recvfrom);
  255. PHP_FUNCTION(socket_sendto);
  256. PHP_FUNCTION(socket_get_option);
  257. PHP_FUNCTION(socket_set_option);
  258. #ifdef HAVE_SHUTDOWN
  259. PHP_FUNCTION(socket_shutdown);
  260. #endif
  261. PHP_FUNCTION(socket_last_error);
  262. PHP_FUNCTION(socket_clear_error);
  263. PHP_FUNCTION(socket_import_stream);
  264. /* {{{ sockets_functions[]
  265. */
  266. const zend_function_entry sockets_functions[] = {
  267. PHP_FE(socket_select, arginfo_socket_select)
  268. PHP_FE(socket_create, arginfo_socket_create)
  269. PHP_FE(socket_create_listen, arginfo_socket_create_listen)
  270. #ifdef HAVE_SOCKETPAIR
  271. PHP_FE(socket_create_pair, arginfo_socket_create_pair)
  272. #endif
  273. PHP_FE(socket_accept, arginfo_socket_accept)
  274. PHP_FE(socket_set_nonblock, arginfo_socket_set_nonblock)
  275. PHP_FE(socket_set_block, arginfo_socket_set_block)
  276. PHP_FE(socket_listen, arginfo_socket_listen)
  277. PHP_FE(socket_close, arginfo_socket_close)
  278. PHP_FE(socket_write, arginfo_socket_write)
  279. PHP_FE(socket_read, arginfo_socket_read)
  280. PHP_FE(socket_getsockname, arginfo_socket_getsockname)
  281. PHP_FE(socket_getpeername, arginfo_socket_getpeername)
  282. PHP_FE(socket_connect, arginfo_socket_connect)
  283. PHP_FE(socket_strerror, arginfo_socket_strerror)
  284. PHP_FE(socket_bind, arginfo_socket_bind)
  285. PHP_FE(socket_recv, arginfo_socket_recv)
  286. PHP_FE(socket_send, arginfo_socket_send)
  287. PHP_FE(socket_recvfrom, arginfo_socket_recvfrom)
  288. PHP_FE(socket_sendto, arginfo_socket_sendto)
  289. PHP_FE(socket_get_option, arginfo_socket_get_option)
  290. PHP_FE(socket_set_option, arginfo_socket_set_option)
  291. #ifdef HAVE_SHUTDOWN
  292. PHP_FE(socket_shutdown, arginfo_socket_shutdown)
  293. #endif
  294. PHP_FE(socket_last_error, arginfo_socket_last_error)
  295. PHP_FE(socket_clear_error, arginfo_socket_clear_error)
  296. PHP_FE(socket_import_stream, arginfo_socket_import_stream)
  297. PHP_FE(socket_sendmsg, arginfo_socket_sendmsg)
  298. PHP_FE(socket_recvmsg, arginfo_socket_recvmsg)
  299. PHP_FE(socket_cmsg_space, arginfo_socket_cmsg_space)
  300. /* for downwards compatibility */
  301. PHP_FALIAS(socket_getopt, socket_get_option, arginfo_socket_get_option)
  302. PHP_FALIAS(socket_setopt, socket_set_option, arginfo_socket_set_option)
  303. PHP_FE_END
  304. };
  305. /* }}} */
  306. zend_module_entry sockets_module_entry = {
  307. STANDARD_MODULE_HEADER,
  308. "sockets",
  309. sockets_functions,
  310. PHP_MINIT(sockets),
  311. PHP_MSHUTDOWN(sockets),
  312. NULL,
  313. PHP_RSHUTDOWN(sockets),
  314. PHP_MINFO(sockets),
  315. NO_VERSION_YET,
  316. PHP_MODULE_GLOBALS(sockets),
  317. PHP_GINIT(sockets),
  318. NULL,
  319. NULL,
  320. STANDARD_MODULE_PROPERTIES_EX
  321. };
  322. #ifdef COMPILE_DL_SOCKETS
  323. ZEND_GET_MODULE(sockets)
  324. #endif
  325. /* inet_ntop should be used instead of inet_ntoa */
  326. int inet_ntoa_lock = 0;
  327. PHP_SOCKETS_API int php_sockets_le_socket(void) /* {{{ */
  328. {
  329. return le_socket;
  330. }
  331. /* }}} */
  332. /* allocating function to make programming errors due to uninitialized fields
  333. * less likely */
  334. static php_socket *php_create_socket(void) /* {{{ */
  335. {
  336. php_socket *php_sock = emalloc(sizeof *php_sock);
  337. php_sock->bsd_socket = -1; /* invalid socket */
  338. php_sock->type = PF_UNSPEC;
  339. php_sock->error = 0;
  340. php_sock->blocking = 1;
  341. php_sock->zstream = NULL;
  342. return php_sock;
  343. }
  344. /* }}} */
  345. static void php_destroy_socket(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
  346. {
  347. php_socket *php_sock = rsrc->ptr;
  348. if (php_sock->zstream == NULL) {
  349. if (!IS_INVALID_SOCKET(php_sock)) {
  350. close(php_sock->bsd_socket);
  351. }
  352. } else {
  353. zval_ptr_dtor(&php_sock->zstream);
  354. }
  355. efree(php_sock);
  356. }
  357. /* }}} */
  358. static int php_open_listen_sock(php_socket **php_sock, int port, int backlog TSRMLS_DC) /* {{{ */
  359. {
  360. struct sockaddr_in la;
  361. struct hostent *hp;
  362. php_socket *sock = php_create_socket();
  363. *php_sock = sock;
  364. #ifndef PHP_WIN32
  365. if ((hp = gethostbyname("0.0.0.0")) == NULL) {
  366. #else
  367. if ((hp = gethostbyname("localhost")) == NULL) {
  368. #endif
  369. efree(sock);
  370. return 0;
  371. }
  372. memcpy((char *) &la.sin_addr, hp->h_addr, hp->h_length);
  373. la.sin_family = hp->h_addrtype;
  374. la.sin_port = htons((unsigned short) port);
  375. sock->bsd_socket = socket(PF_INET, SOCK_STREAM, 0);
  376. sock->blocking = 1;
  377. if (IS_INVALID_SOCKET(sock)) {
  378. PHP_SOCKET_ERROR(sock, "unable to create listening socket", errno);
  379. efree(sock);
  380. return 0;
  381. }
  382. sock->type = PF_INET;
  383. if (bind(sock->bsd_socket, (struct sockaddr *)&la, sizeof(la)) != 0) {
  384. PHP_SOCKET_ERROR(sock, "unable to bind to given address", errno);
  385. close(sock->bsd_socket);
  386. efree(sock);
  387. return 0;
  388. }
  389. if (listen(sock->bsd_socket, backlog) != 0) {
  390. PHP_SOCKET_ERROR(sock, "unable to listen on socket", errno);
  391. close(sock->bsd_socket);
  392. efree(sock);
  393. return 0;
  394. }
  395. return 1;
  396. }
  397. /* }}} */
  398. static int php_accept_connect(php_socket *in_sock, php_socket **new_sock, struct sockaddr *la, socklen_t *la_len TSRMLS_DC) /* {{{ */
  399. {
  400. php_socket *out_sock = php_create_socket();
  401. *new_sock = out_sock;
  402. out_sock->bsd_socket = accept(in_sock->bsd_socket, la, la_len);
  403. if (IS_INVALID_SOCKET(out_sock)) {
  404. PHP_SOCKET_ERROR(out_sock, "unable to accept incoming connection", errno);
  405. efree(out_sock);
  406. return 0;
  407. }
  408. out_sock->error = 0;
  409. out_sock->blocking = 1;
  410. out_sock->type = la->sa_family;
  411. return 1;
  412. }
  413. /* }}} */
  414. /* {{{ php_read -- wrapper around read() so that it only reads to a \r or \n. */
  415. static int php_read(php_socket *sock, void *buf, size_t maxlen, int flags)
  416. {
  417. int m = 0;
  418. size_t n = 0;
  419. int no_read = 0;
  420. int nonblock = 0;
  421. char *t = (char *) buf;
  422. #ifndef PHP_WIN32
  423. m = fcntl(sock->bsd_socket, F_GETFL);
  424. if (m < 0) {
  425. return m;
  426. }
  427. nonblock = (m & O_NONBLOCK);
  428. m = 0;
  429. #else
  430. nonblock = !sock->blocking;
  431. #endif
  432. set_errno(0);
  433. *t = '\0';
  434. while (*t != '\n' && *t != '\r' && n < maxlen) {
  435. if (m > 0) {
  436. t++;
  437. n++;
  438. } else if (m == 0) {
  439. no_read++;
  440. if (nonblock && no_read >= 2) {
  441. return n;
  442. /* The first pass, m always is 0, so no_read becomes 1
  443. * in the first pass. no_read becomes 2 in the second pass,
  444. * and if this is nonblocking, we should return.. */
  445. }
  446. if (no_read > 200) {
  447. set_errno(ECONNRESET);
  448. return -1;
  449. }
  450. }
  451. if (n < maxlen) {
  452. m = recv(sock->bsd_socket, (void *) t, 1, flags);
  453. }
  454. if (errno != 0 && errno != ESPIPE && errno != EAGAIN) {
  455. return -1;
  456. }
  457. set_errno(0);
  458. }
  459. if (n < maxlen) {
  460. n++;
  461. /* The only reasons it makes it to here is
  462. * if '\n' or '\r' are encountered. So, increase
  463. * the return by 1 to make up for the lack of the
  464. * '\n' or '\r' in the count (since read() takes
  465. * place at the end of the loop..) */
  466. }
  467. return n;
  468. }
  469. /* }}} */
  470. char *sockets_strerror(int error TSRMLS_DC) /* {{{ */
  471. {
  472. const char *buf;
  473. #ifndef PHP_WIN32
  474. if (error < -10000) {
  475. error = -error - 10000;
  476. #ifdef HAVE_HSTRERROR
  477. buf = hstrerror(error);
  478. #else
  479. {
  480. if (SOCKETS_G(strerror_buf)) {
  481. efree(SOCKETS_G(strerror_buf));
  482. }
  483. spprintf(&(SOCKETS_G(strerror_buf)), 0, "Host lookup error %d", error);
  484. buf = SOCKETS_G(strerror_buf);
  485. }
  486. #endif
  487. } else {
  488. buf = strerror(error);
  489. }
  490. #else
  491. {
  492. LPTSTR tmp = NULL;
  493. buf = NULL;
  494. if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  495. NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &tmp, 0, NULL)
  496. ) {
  497. if (SOCKETS_G(strerror_buf)) {
  498. efree(SOCKETS_G(strerror_buf));
  499. }
  500. SOCKETS_G(strerror_buf) = estrdup(tmp);
  501. LocalFree(tmp);
  502. buf = SOCKETS_G(strerror_buf);
  503. }
  504. }
  505. #endif
  506. return (buf ? (char *) buf : "");
  507. }
  508. /* }}} */
  509. /* {{{ PHP_GINIT_FUNCTION */
  510. static PHP_GINIT_FUNCTION(sockets)
  511. {
  512. sockets_globals->last_error = 0;
  513. sockets_globals->strerror_buf = NULL;
  514. }
  515. /* }}} */
  516. /* {{{ PHP_MINIT_FUNCTION
  517. */
  518. static PHP_MINIT_FUNCTION(sockets)
  519. {
  520. le_socket = zend_register_list_destructors_ex(php_destroy_socket, NULL, le_socket_name, module_number);
  521. REGISTER_LONG_CONSTANT("AF_UNIX", AF_UNIX, CONST_CS | CONST_PERSISTENT);
  522. REGISTER_LONG_CONSTANT("AF_INET", AF_INET, CONST_CS | CONST_PERSISTENT);
  523. #if HAVE_IPV6
  524. REGISTER_LONG_CONSTANT("AF_INET6", AF_INET6, CONST_CS | CONST_PERSISTENT);
  525. #endif
  526. REGISTER_LONG_CONSTANT("SOCK_STREAM", SOCK_STREAM, CONST_CS | CONST_PERSISTENT);
  527. REGISTER_LONG_CONSTANT("SOCK_DGRAM", SOCK_DGRAM, CONST_CS | CONST_PERSISTENT);
  528. REGISTER_LONG_CONSTANT("SOCK_RAW", SOCK_RAW, CONST_CS | CONST_PERSISTENT);
  529. REGISTER_LONG_CONSTANT("SOCK_SEQPACKET",SOCK_SEQPACKET, CONST_CS | CONST_PERSISTENT);
  530. REGISTER_LONG_CONSTANT("SOCK_RDM", SOCK_RDM, CONST_CS | CONST_PERSISTENT);
  531. REGISTER_LONG_CONSTANT("MSG_OOB", MSG_OOB, CONST_CS | CONST_PERSISTENT);
  532. REGISTER_LONG_CONSTANT("MSG_WAITALL", MSG_WAITALL, CONST_CS | CONST_PERSISTENT);
  533. REGISTER_LONG_CONSTANT("MSG_CTRUNC", MSG_CTRUNC, CONST_CS | CONST_PERSISTENT);
  534. REGISTER_LONG_CONSTANT("MSG_TRUNC", MSG_TRUNC, CONST_CS | CONST_PERSISTENT);
  535. REGISTER_LONG_CONSTANT("MSG_PEEK", MSG_PEEK, CONST_CS | CONST_PERSISTENT);
  536. REGISTER_LONG_CONSTANT("MSG_DONTROUTE", MSG_DONTROUTE, CONST_CS | CONST_PERSISTENT);
  537. #ifdef MSG_EOR
  538. REGISTER_LONG_CONSTANT("MSG_EOR", MSG_EOR, CONST_CS | CONST_PERSISTENT);
  539. #endif
  540. #ifdef MSG_EOF
  541. REGISTER_LONG_CONSTANT("MSG_EOF", MSG_EOF, CONST_CS | CONST_PERSISTENT);
  542. #endif
  543. #ifdef MSG_CONFIRM
  544. REGISTER_LONG_CONSTANT("MSG_CONFIRM", MSG_CONFIRM, CONST_CS | CONST_PERSISTENT);
  545. #endif
  546. #ifdef MSG_ERRQUEUE
  547. REGISTER_LONG_CONSTANT("MSG_ERRQUEUE", MSG_ERRQUEUE, CONST_CS | CONST_PERSISTENT);
  548. #endif
  549. #ifdef MSG_NOSIGNAL
  550. REGISTER_LONG_CONSTANT("MSG_NOSIGNAL", MSG_NOSIGNAL, CONST_CS | CONST_PERSISTENT);
  551. #endif
  552. #ifdef MSG_DONTWAIT
  553. REGISTER_LONG_CONSTANT("MSG_DONTWAIT", MSG_DONTWAIT, CONST_CS | CONST_PERSISTENT);
  554. #endif
  555. #ifdef MSG_MORE
  556. REGISTER_LONG_CONSTANT("MSG_MORE", MSG_MORE, CONST_CS | CONST_PERSISTENT);
  557. #endif
  558. #ifdef MSG_WAITFORONE
  559. REGISTER_LONG_CONSTANT("MSG_WAITFORONE",MSG_WAITFORONE, CONST_CS | CONST_PERSISTENT);
  560. #endif
  561. #ifdef MSG_CMSG_CLOEXEC
  562. REGISTER_LONG_CONSTANT("MSG_CMSG_CLOEXEC",MSG_CMSG_CLOEXEC,CONST_CS | CONST_PERSISTENT);
  563. #endif
  564. REGISTER_LONG_CONSTANT("SO_DEBUG", SO_DEBUG, CONST_CS | CONST_PERSISTENT);
  565. REGISTER_LONG_CONSTANT("SO_REUSEADDR", SO_REUSEADDR, CONST_CS | CONST_PERSISTENT);
  566. #ifdef SO_REUSEPORT
  567. REGISTER_LONG_CONSTANT("SO_REUSEPORT", SO_REUSEPORT, CONST_CS | CONST_PERSISTENT);
  568. #endif
  569. REGISTER_LONG_CONSTANT("SO_KEEPALIVE", SO_KEEPALIVE, CONST_CS | CONST_PERSISTENT);
  570. REGISTER_LONG_CONSTANT("SO_DONTROUTE", SO_DONTROUTE, CONST_CS | CONST_PERSISTENT);
  571. REGISTER_LONG_CONSTANT("SO_LINGER", SO_LINGER, CONST_CS | CONST_PERSISTENT);
  572. REGISTER_LONG_CONSTANT("SO_BROADCAST", SO_BROADCAST, CONST_CS | CONST_PERSISTENT);
  573. REGISTER_LONG_CONSTANT("SO_OOBINLINE", SO_OOBINLINE, CONST_CS | CONST_PERSISTENT);
  574. REGISTER_LONG_CONSTANT("SO_SNDBUF", SO_SNDBUF, CONST_CS | CONST_PERSISTENT);
  575. REGISTER_LONG_CONSTANT("SO_RCVBUF", SO_RCVBUF, CONST_CS | CONST_PERSISTENT);
  576. REGISTER_LONG_CONSTANT("SO_SNDLOWAT", SO_SNDLOWAT, CONST_CS | CONST_PERSISTENT);
  577. REGISTER_LONG_CONSTANT("SO_RCVLOWAT", SO_RCVLOWAT, CONST_CS | CONST_PERSISTENT);
  578. REGISTER_LONG_CONSTANT("SO_SNDTIMEO", SO_SNDTIMEO, CONST_CS | CONST_PERSISTENT);
  579. REGISTER_LONG_CONSTANT("SO_RCVTIMEO", SO_RCVTIMEO, CONST_CS | CONST_PERSISTENT);
  580. REGISTER_LONG_CONSTANT("SO_TYPE", SO_TYPE, CONST_CS | CONST_PERSISTENT);
  581. #ifdef SO_FAMILY
  582. REGISTER_LONG_CONSTANT("SO_FAMILY", SO_FAMILY, CONST_CS | CONST_PERSISTENT);
  583. #endif
  584. REGISTER_LONG_CONSTANT("SO_ERROR", SO_ERROR, CONST_CS | CONST_PERSISTENT);
  585. #ifdef SO_BINDTODEVICE
  586. REGISTER_LONG_CONSTANT("SO_BINDTODEVICE", SO_BINDTODEVICE, CONST_CS | CONST_PERSISTENT);
  587. #endif
  588. REGISTER_LONG_CONSTANT("SOL_SOCKET", SOL_SOCKET, CONST_CS | CONST_PERSISTENT);
  589. REGISTER_LONG_CONSTANT("SOMAXCONN", SOMAXCONN, CONST_CS | CONST_PERSISTENT);
  590. #ifdef TCP_NODELAY
  591. REGISTER_LONG_CONSTANT("TCP_NODELAY", TCP_NODELAY, CONST_CS | CONST_PERSISTENT);
  592. #endif
  593. REGISTER_LONG_CONSTANT("PHP_NORMAL_READ", PHP_NORMAL_READ, CONST_CS | CONST_PERSISTENT);
  594. REGISTER_LONG_CONSTANT("PHP_BINARY_READ", PHP_BINARY_READ, CONST_CS | CONST_PERSISTENT);
  595. REGISTER_LONG_CONSTANT("MCAST_JOIN_GROUP", PHP_MCAST_JOIN_GROUP, CONST_CS | CONST_PERSISTENT);
  596. REGISTER_LONG_CONSTANT("MCAST_LEAVE_GROUP", PHP_MCAST_LEAVE_GROUP, CONST_CS | CONST_PERSISTENT);
  597. #ifdef HAS_MCAST_EXT
  598. REGISTER_LONG_CONSTANT("MCAST_BLOCK_SOURCE", PHP_MCAST_BLOCK_SOURCE, CONST_CS | CONST_PERSISTENT);
  599. REGISTER_LONG_CONSTANT("MCAST_UNBLOCK_SOURCE", PHP_MCAST_UNBLOCK_SOURCE, CONST_CS | CONST_PERSISTENT);
  600. REGISTER_LONG_CONSTANT("MCAST_JOIN_SOURCE_GROUP", PHP_MCAST_JOIN_SOURCE_GROUP, CONST_CS | CONST_PERSISTENT);
  601. REGISTER_LONG_CONSTANT("MCAST_LEAVE_SOURCE_GROUP", PHP_MCAST_LEAVE_SOURCE_GROUP, CONST_CS | CONST_PERSISTENT);
  602. #endif
  603. REGISTER_LONG_CONSTANT("IP_MULTICAST_IF", IP_MULTICAST_IF, CONST_CS | CONST_PERSISTENT);
  604. REGISTER_LONG_CONSTANT("IP_MULTICAST_TTL", IP_MULTICAST_TTL, CONST_CS | CONST_PERSISTENT);
  605. REGISTER_LONG_CONSTANT("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP, CONST_CS | CONST_PERSISTENT);
  606. #if HAVE_IPV6
  607. REGISTER_LONG_CONSTANT("IPV6_MULTICAST_IF", IPV6_MULTICAST_IF, CONST_CS | CONST_PERSISTENT);
  608. REGISTER_LONG_CONSTANT("IPV6_MULTICAST_HOPS", IPV6_MULTICAST_HOPS, CONST_CS | CONST_PERSISTENT);
  609. REGISTER_LONG_CONSTANT("IPV6_MULTICAST_LOOP", IPV6_MULTICAST_LOOP, CONST_CS | CONST_PERSISTENT);
  610. #endif
  611. #ifndef WIN32
  612. # include "unix_socket_constants.h"
  613. #else
  614. # include "win32_socket_constants.h"
  615. #endif
  616. REGISTER_LONG_CONSTANT("IPPROTO_IP", IPPROTO_IP, CONST_CS | CONST_PERSISTENT);
  617. #if HAVE_IPV6
  618. REGISTER_LONG_CONSTANT("IPPROTO_IPV6", IPPROTO_IPV6, CONST_CS | CONST_PERSISTENT);
  619. #endif
  620. REGISTER_LONG_CONSTANT("SOL_TCP", IPPROTO_TCP, CONST_CS | CONST_PERSISTENT);
  621. REGISTER_LONG_CONSTANT("SOL_UDP", IPPROTO_UDP, CONST_CS | CONST_PERSISTENT);
  622. #if HAVE_IPV6
  623. REGISTER_LONG_CONSTANT("IPV6_UNICAST_HOPS", IPV6_UNICAST_HOPS, CONST_CS | CONST_PERSISTENT);
  624. #endif
  625. php_socket_sendrecvmsg_init(INIT_FUNC_ARGS_PASSTHRU);
  626. return SUCCESS;
  627. }
  628. /* }}} */
  629. /* {{{ PHP_MSHUTDOWN_FUNCTION
  630. */
  631. static PHP_MSHUTDOWN_FUNCTION(sockets)
  632. {
  633. php_socket_sendrecvmsg_shutdown(SHUTDOWN_FUNC_ARGS_PASSTHRU);
  634. return SUCCESS;
  635. }
  636. /* }}} */
  637. /* {{{ PHP_MINFO_FUNCTION
  638. */
  639. static PHP_MINFO_FUNCTION(sockets)
  640. {
  641. php_info_print_table_start();
  642. php_info_print_table_row(2, "Sockets Support", "enabled");
  643. php_info_print_table_end();
  644. }
  645. /* }}} */
  646. /* {{{ PHP_RSHUTDOWN_FUNCTION */
  647. static PHP_RSHUTDOWN_FUNCTION(sockets)
  648. {
  649. if (SOCKETS_G(strerror_buf)) {
  650. efree(SOCKETS_G(strerror_buf));
  651. SOCKETS_G(strerror_buf) = NULL;
  652. }
  653. return SUCCESS;
  654. }
  655. /* }}} */
  656. static int php_sock_array_to_fd_set(zval *sock_array, fd_set *fds, PHP_SOCKET *max_fd TSRMLS_DC) /* {{{ */
  657. {
  658. zval **element;
  659. php_socket *php_sock;
  660. int num = 0;
  661. if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0;
  662. for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(sock_array));
  663. zend_hash_get_current_data(Z_ARRVAL_P(sock_array), (void **) &element) == SUCCESS;
  664. zend_hash_move_forward(Z_ARRVAL_P(sock_array))) {
  665. php_sock = (php_socket*) zend_fetch_resource(element TSRMLS_CC, -1, le_socket_name, NULL, 1, le_socket);
  666. if (!php_sock) continue; /* If element is not a resource, skip it */
  667. PHP_SAFE_FD_SET(php_sock->bsd_socket, fds);
  668. if (php_sock->bsd_socket > *max_fd) {
  669. *max_fd = php_sock->bsd_socket;
  670. }
  671. num++;
  672. }
  673. return num ? 1 : 0;
  674. }
  675. /* }}} */
  676. static int php_sock_array_from_fd_set(zval *sock_array, fd_set *fds TSRMLS_DC) /* {{{ */
  677. {
  678. zval **element;
  679. zval **dest_element;
  680. php_socket *php_sock;
  681. HashTable *new_hash;
  682. char *key;
  683. int num = 0;
  684. ulong num_key;
  685. uint key_len;
  686. if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0;
  687. ALLOC_HASHTABLE(new_hash);
  688. zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(sock_array)), NULL, ZVAL_PTR_DTOR, 0);
  689. for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(sock_array));
  690. zend_hash_get_current_data(Z_ARRVAL_P(sock_array), (void **) &element) == SUCCESS;
  691. zend_hash_move_forward(Z_ARRVAL_P(sock_array))) {
  692. php_sock = (php_socket*) zend_fetch_resource(element TSRMLS_CC, -1, le_socket_name, NULL, 1, le_socket);
  693. if (!php_sock) continue; /* If element is not a resource, skip it */
  694. if (PHP_SAFE_FD_ISSET(php_sock->bsd_socket, fds)) {
  695. /* Add fd to new array */
  696. switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(sock_array), &key, &key_len, &num_key, 0, NULL)) {
  697. case HASH_KEY_IS_STRING:
  698. zend_hash_add(new_hash, key, key_len, (void *)element, sizeof(zval *), (void **)&dest_element);
  699. break;
  700. case HASH_KEY_IS_LONG:
  701. zend_hash_index_update(new_hash, num_key, (void *)element, sizeof(zval *), (void **)&dest_element);
  702. break;
  703. }
  704. if (dest_element) zval_add_ref(dest_element);
  705. }
  706. num++;
  707. }
  708. /* Destroy old array, add new one */
  709. zend_hash_destroy(Z_ARRVAL_P(sock_array));
  710. efree(Z_ARRVAL_P(sock_array));
  711. zend_hash_internal_pointer_reset(new_hash);
  712. Z_ARRVAL_P(sock_array) = new_hash;
  713. return num ? 1 : 0;
  714. }
  715. /* }}} */
  716. /* {{{ proto int socket_select(array &read_fds, array &write_fds, array &except_fds, int tv_sec[, int tv_usec]) U
  717. Runs the select() system call on the sets mentioned with a timeout specified by tv_sec and tv_usec */
  718. PHP_FUNCTION(socket_select)
  719. {
  720. zval *r_array, *w_array, *e_array, *sec;
  721. struct timeval tv;
  722. struct timeval *tv_p = NULL;
  723. fd_set rfds, wfds, efds;
  724. PHP_SOCKET max_fd = 0;
  725. int retval, sets = 0;
  726. long usec = 0;
  727. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!z!|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE) {
  728. return;
  729. }
  730. FD_ZERO(&rfds);
  731. FD_ZERO(&wfds);
  732. FD_ZERO(&efds);
  733. if (r_array != NULL) sets += php_sock_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC);
  734. if (w_array != NULL) sets += php_sock_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC);
  735. if (e_array != NULL) sets += php_sock_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC);
  736. if (!sets) {
  737. php_error_docref(NULL TSRMLS_CC, E_WARNING, "no resource arrays were passed to select");
  738. RETURN_FALSE;
  739. }
  740. PHP_SAFE_MAX_FD(max_fd, 0); /* someone needs to make this look more like stream_socket_select */
  741. /* If seconds is not set to null, build the timeval, else we wait indefinitely */
  742. if (sec != NULL) {
  743. zval tmp;
  744. if (Z_TYPE_P(sec) != IS_LONG) {
  745. tmp = *sec;
  746. zval_copy_ctor(&tmp);
  747. convert_to_long(&tmp);
  748. sec = &tmp;
  749. }
  750. /* Solaris + BSD do not like microsecond values which are >= 1 sec */
  751. if (usec > 999999) {
  752. tv.tv_sec = Z_LVAL_P(sec) + (usec / 1000000);
  753. tv.tv_usec = usec % 1000000;
  754. } else {
  755. tv.tv_sec = Z_LVAL_P(sec);
  756. tv.tv_usec = usec;
  757. }
  758. tv_p = &tv;
  759. if (sec == &tmp) {
  760. zval_dtor(&tmp);
  761. }
  762. }
  763. retval = select(max_fd+1, &rfds, &wfds, &efds, tv_p);
  764. if (retval == -1) {
  765. SOCKETS_G(last_error) = errno;
  766. php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s", errno, sockets_strerror(errno TSRMLS_CC));
  767. RETURN_FALSE;
  768. }
  769. if (r_array != NULL) php_sock_array_from_fd_set(r_array, &rfds TSRMLS_CC);
  770. if (w_array != NULL) php_sock_array_from_fd_set(w_array, &wfds TSRMLS_CC);
  771. if (e_array != NULL) php_sock_array_from_fd_set(e_array, &efds TSRMLS_CC);
  772. RETURN_LONG(retval);
  773. }
  774. /* }}} */
  775. /* {{{ proto resource socket_create_listen(int port[, int backlog]) U
  776. Opens a socket on port to accept connections */
  777. PHP_FUNCTION(socket_create_listen)
  778. {
  779. php_socket *php_sock;
  780. long port, backlog = 128;
  781. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &port, &backlog) == FAILURE) {
  782. return;
  783. }
  784. if (!php_open_listen_sock(&php_sock, port, backlog TSRMLS_CC)) {
  785. RETURN_FALSE;
  786. }
  787. php_sock->error = 0;
  788. php_sock->blocking = 1;
  789. ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);
  790. }
  791. /* }}} */
  792. /* {{{ proto resource socket_accept(resource socket) U
  793. Accepts a connection on the listening socket fd */
  794. PHP_FUNCTION(socket_accept)
  795. {
  796. zval *arg1;
  797. php_socket *php_sock, *new_sock;
  798. php_sockaddr_storage sa;
  799. socklen_t php_sa_len = sizeof(sa);
  800. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
  801. return;
  802. }
  803. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  804. if (!php_accept_connect(php_sock, &new_sock, (struct sockaddr*)&sa, &php_sa_len TSRMLS_CC)) {
  805. RETURN_FALSE;
  806. }
  807. ZEND_REGISTER_RESOURCE(return_value, new_sock, le_socket);
  808. }
  809. /* }}} */
  810. /* {{{ proto bool socket_set_nonblock(resource socket) U
  811. Sets nonblocking mode on a socket resource */
  812. PHP_FUNCTION(socket_set_nonblock)
  813. {
  814. zval *arg1;
  815. php_socket *php_sock;
  816. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
  817. return;
  818. }
  819. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  820. if (php_sock->zstream != NULL) {
  821. php_stream *stream;
  822. /* omit notice if resource doesn't exist anymore */
  823. stream = zend_fetch_resource(&php_sock->zstream TSRMLS_CC, -1,
  824. NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
  825. if (stream != NULL) {
  826. if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, 0,
  827. NULL) != -1) {
  828. php_sock->blocking = 0;
  829. RETURN_TRUE;
  830. }
  831. }
  832. }
  833. if (php_set_sock_blocking(php_sock->bsd_socket, 0 TSRMLS_CC) == SUCCESS) {
  834. php_sock->blocking = 0;
  835. RETURN_TRUE;
  836. } else {
  837. PHP_SOCKET_ERROR(php_sock, "unable to set nonblocking mode", errno);
  838. RETURN_FALSE;
  839. }
  840. }
  841. /* }}} */
  842. /* {{{ proto bool socket_set_block(resource socket) U
  843. Sets blocking mode on a socket resource */
  844. PHP_FUNCTION(socket_set_block)
  845. {
  846. zval *arg1;
  847. php_socket *php_sock;
  848. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
  849. return;
  850. }
  851. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  852. /* if socket was created from a stream, give the stream a chance to take
  853. * care of the operation itself, thereby allowing it to update its internal
  854. * state */
  855. if (php_sock->zstream != NULL) {
  856. php_stream *stream;
  857. stream = zend_fetch_resource(&php_sock->zstream TSRMLS_CC, -1,
  858. NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
  859. if (stream != NULL) {
  860. if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, 1,
  861. NULL) != -1) {
  862. php_sock->blocking = 1;
  863. RETURN_TRUE;
  864. }
  865. }
  866. }
  867. if (php_set_sock_blocking(php_sock->bsd_socket, 1 TSRMLS_CC) == SUCCESS) {
  868. php_sock->blocking = 1;
  869. RETURN_TRUE;
  870. } else {
  871. PHP_SOCKET_ERROR(php_sock, "unable to set blocking mode", errno);
  872. RETURN_FALSE;
  873. }
  874. }
  875. /* }}} */
  876. /* {{{ proto bool socket_listen(resource socket[, int backlog]) U
  877. Sets the maximum number of connections allowed to be waited for on the socket specified by fd */
  878. PHP_FUNCTION(socket_listen)
  879. {
  880. zval *arg1;
  881. php_socket *php_sock;
  882. long backlog = 0;
  883. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &arg1, &backlog) == FAILURE) {
  884. return;
  885. }
  886. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  887. if (listen(php_sock->bsd_socket, backlog) != 0) {
  888. PHP_SOCKET_ERROR(php_sock, "unable to listen on socket", errno);
  889. RETURN_FALSE;
  890. }
  891. RETURN_TRUE;
  892. }
  893. /* }}} */
  894. /* {{{ proto void socket_close(resource socket) U
  895. Closes a file descriptor */
  896. PHP_FUNCTION(socket_close)
  897. {
  898. zval *arg1;
  899. php_socket *php_sock;
  900. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
  901. return;
  902. }
  903. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  904. if (php_sock->zstream != NULL) {
  905. php_stream *stream = NULL;
  906. php_stream_from_zval_no_verify(stream, &php_sock->zstream);
  907. if (stream != NULL) {
  908. /* close & destroy stream, incl. removing it from the rsrc list;
  909. * resource stored in php_sock->zstream will become invalid */
  910. php_stream_free(stream, PHP_STREAM_FREE_CLOSE |
  911. (stream->is_persistent?PHP_STREAM_FREE_CLOSE_PERSISTENT:0));
  912. }
  913. }
  914. zend_list_delete(Z_RESVAL_P(arg1));
  915. }
  916. /* }}} */
  917. /* {{{ proto int socket_write(resource socket, string buf[, int length])
  918. Writes the buffer to the socket resource, length is optional */
  919. PHP_FUNCTION(socket_write)
  920. {
  921. zval *arg1;
  922. php_socket *php_sock;
  923. int retval, str_len;
  924. long length = 0;
  925. char *str;
  926. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &str, &str_len, &length) == FAILURE) {
  927. return;
  928. }
  929. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  930. if (ZEND_NUM_ARGS() < 3) {
  931. length = str_len;
  932. }
  933. #ifndef PHP_WIN32
  934. retval = write(php_sock->bsd_socket, str, MIN(length, str_len));
  935. #else
  936. retval = send(php_sock->bsd_socket, str, min(length, str_len), 0);
  937. #endif
  938. if (retval < 0) {
  939. PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);
  940. RETURN_FALSE;
  941. }
  942. RETURN_LONG(retval);
  943. }
  944. /* }}} */
  945. /* {{{ proto string socket_read(resource socket, int length [, int type]) U
  946. Reads a maximum of length bytes from socket */
  947. PHP_FUNCTION(socket_read)
  948. {
  949. zval *arg1;
  950. php_socket *php_sock;
  951. char *tmpbuf;
  952. int retval;
  953. long length, type = PHP_BINARY_READ;
  954. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|l", &arg1, &length, &type) == FAILURE) {
  955. return;
  956. }
  957. /* overflow check */
  958. if ((length + 1) < 2) {
  959. RETURN_FALSE;
  960. }
  961. tmpbuf = emalloc(length + 1);
  962. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  963. if (type == PHP_NORMAL_READ) {
  964. retval = php_read(php_sock, tmpbuf, length, 0);
  965. } else {
  966. retval = recv(php_sock->bsd_socket, tmpbuf, length, 0);
  967. }
  968. if (retval == -1) {
  969. /* if the socket is in non-blocking mode and there's no data to read,
  970. don't output any error, as this is a normal situation, and not an error */
  971. if (errno == EAGAIN
  972. #ifdef EWOULDBLOCK
  973. || errno == EWOULDBLOCK
  974. #endif
  975. ) {
  976. php_sock->error = errno;
  977. SOCKETS_G(last_error) = errno;
  978. } else {
  979. PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno);
  980. }
  981. efree(tmpbuf);
  982. RETURN_FALSE;
  983. } else if (!retval) {
  984. efree(tmpbuf);
  985. RETURN_EMPTY_STRING();
  986. }
  987. tmpbuf = erealloc(tmpbuf, retval + 1);
  988. tmpbuf[retval] = '\0' ;
  989. RETURN_STRINGL(tmpbuf, retval, 0);
  990. }
  991. /* }}} */
  992. /* {{{ proto bool socket_getsockname(resource socket, string &addr[, int &port])
  993. Queries the remote side of the given socket which may either result in host/port or in a UNIX filesystem path, dependent on its type. */
  994. PHP_FUNCTION(socket_getsockname)
  995. {
  996. zval *arg1, *addr, *port = NULL;
  997. php_sockaddr_storage sa_storage;
  998. php_socket *php_sock;
  999. struct sockaddr *sa;
  1000. struct sockaddr_in *sin;
  1001. #if HAVE_IPV6
  1002. struct sockaddr_in6 *sin6;
  1003. char addr6[INET6_ADDRSTRLEN+1];
  1004. #endif
  1005. struct sockaddr_un *s_un;
  1006. char *addr_string;
  1007. socklen_t salen = sizeof(php_sockaddr_storage);
  1008. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|z", &arg1, &addr, &port) == FAILURE) {
  1009. return;
  1010. }
  1011. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  1012. sa = (struct sockaddr *) &sa_storage;
  1013. if (getsockname(php_sock->bsd_socket, sa, &salen) != 0) {
  1014. PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket name", errno);
  1015. RETURN_FALSE;
  1016. }
  1017. switch (sa->sa_family) {
  1018. #if HAVE_IPV6
  1019. case AF_INET6:
  1020. sin6 = (struct sockaddr_in6 *) sa;
  1021. inet_ntop(AF_INET6, &sin6->sin6_addr, addr6, INET6_ADDRSTRLEN);
  1022. zval_dtor(addr);
  1023. ZVAL_STRING(addr, addr6, 1);
  1024. if (port != NULL) {
  1025. zval_dtor(port);
  1026. ZVAL_LONG(port, htons(sin6->sin6_port));
  1027. }
  1028. RETURN_TRUE;
  1029. break;
  1030. #endif
  1031. case AF_INET:
  1032. sin = (struct sockaddr_in *) sa;
  1033. while (inet_ntoa_lock == 1);
  1034. inet_ntoa_lock = 1;
  1035. addr_string = inet_ntoa(sin->sin_addr);
  1036. inet_ntoa_lock = 0;
  1037. zval_dtor(addr);
  1038. ZVAL_STRING(addr, addr_string, 1);
  1039. if (port != NULL) {
  1040. zval_dtor(port);
  1041. ZVAL_LONG(port, htons(sin->sin_port));
  1042. }
  1043. RETURN_TRUE;
  1044. break;
  1045. case AF_UNIX:
  1046. s_un = (struct sockaddr_un *) sa;
  1047. zval_dtor(addr);
  1048. ZVAL_STRING(addr, s_un->sun_path, 1);
  1049. RETURN_TRUE;
  1050. break;
  1051. default:
  1052. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported address family %d", sa->sa_family);
  1053. RETURN_FALSE;
  1054. }
  1055. }
  1056. /* }}} */
  1057. /* {{{ proto bool socket_getpeername(resource socket, string &addr[, int &port])
  1058. Queries the remote side of the given socket which may either result in host/port or in a UNIX filesystem path, dependent on its type. */
  1059. PHP_FUNCTION(socket_getpeername)
  1060. {
  1061. zval *arg1, *arg2, *arg3 = NULL;
  1062. php_sockaddr_storage sa_storage;
  1063. php_socket *php_sock;
  1064. struct sockaddr *sa;
  1065. struct sockaddr_in *sin;
  1066. #if HAVE_IPV6
  1067. struct sockaddr_in6 *sin6;
  1068. char addr6[INET6_ADDRSTRLEN+1];
  1069. #endif
  1070. struct sockaddr_un *s_un;
  1071. char *addr_string;
  1072. socklen_t salen = sizeof(php_sockaddr_storage);
  1073. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|z", &arg1, &arg2, &arg3) == FAILURE) {
  1074. return;
  1075. }
  1076. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  1077. sa = (struct sockaddr *) &sa_storage;
  1078. if (getpeername(php_sock->bsd_socket, sa, &salen) < 0) {
  1079. PHP_SOCKET_ERROR(php_sock, "unable to retrieve peer name", errno);
  1080. RETURN_FALSE;
  1081. }
  1082. switch (sa->sa_family) {
  1083. #if HAVE_IPV6
  1084. case AF_INET6:
  1085. sin6 = (struct sockaddr_in6 *) sa;
  1086. inet_ntop(AF_INET6, &sin6->sin6_addr, addr6, INET6_ADDRSTRLEN);
  1087. zval_dtor(arg2);
  1088. ZVAL_STRING(arg2, addr6, 1);
  1089. if (arg3 != NULL) {
  1090. zval_dtor(arg3);
  1091. ZVAL_LONG(arg3, htons(sin6->sin6_port));
  1092. }
  1093. RETURN_TRUE;
  1094. break;
  1095. #endif
  1096. case AF_INET:
  1097. sin = (struct sockaddr_in *) sa;
  1098. while (inet_ntoa_lock == 1);
  1099. inet_ntoa_lock = 1;
  1100. addr_string = inet_ntoa(sin->sin_addr);
  1101. inet_ntoa_lock = 0;
  1102. zval_dtor(arg2);
  1103. ZVAL_STRING(arg2, addr_string, 1);
  1104. if (arg3 != NULL) {
  1105. zval_dtor(arg3);
  1106. ZVAL_LONG(arg3, htons(sin->sin_port));
  1107. }
  1108. RETURN_TRUE;
  1109. break;
  1110. case AF_UNIX:
  1111. s_un = (struct sockaddr_un *) sa;
  1112. zval_dtor(arg2);
  1113. ZVAL_STRING(arg2, s_un->sun_path, 1);
  1114. RETURN_TRUE;
  1115. break;
  1116. default:
  1117. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported address family %d", sa->sa_family);
  1118. RETURN_FALSE;
  1119. }
  1120. }
  1121. /* }}} */
  1122. /* {{{ proto resource socket_create(int domain, int type, int protocol) U
  1123. Creates an endpoint for communication in the domain specified by domain, of type specified by type */
  1124. PHP_FUNCTION(socket_create)
  1125. {
  1126. long arg1, arg2, arg3;
  1127. php_socket *php_sock = php_create_socket();
  1128. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &arg1, &arg2, &arg3) == FAILURE) {
  1129. efree(php_sock);
  1130. return;
  1131. }
  1132. if (arg1 != AF_UNIX
  1133. #if HAVE_IPV6
  1134. && arg1 != AF_INET6
  1135. #endif
  1136. && arg1 != AF_INET) {
  1137. php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket domain [%ld] specified for argument 1, assuming AF_INET", arg1);
  1138. arg1 = AF_INET;
  1139. }
  1140. if (arg2 > 10) {
  1141. php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM", arg2);
  1142. arg2 = SOCK_STREAM;
  1143. }
  1144. php_sock->bsd_socket = socket(arg1, arg2, arg3);
  1145. php_sock->type = arg1;
  1146. if (IS_INVALID_SOCKET(php_sock)) {
  1147. SOCKETS_G(last_error) = errno;
  1148. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create socket [%d]: %s", errno, sockets_strerror(errno TSRMLS_CC));
  1149. efree(php_sock);
  1150. RETURN_FALSE;
  1151. }
  1152. php_sock->error = 0;
  1153. php_sock->blocking = 1;
  1154. ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);
  1155. }
  1156. /* }}} */
  1157. /* {{{ proto bool socket_connect(resource socket, string addr [, int port])
  1158. Opens a connection to addr:port on the socket specified by socket */
  1159. PHP_FUNCTION(socket_connect)
  1160. {
  1161. zval *arg1;
  1162. php_socket *php_sock;
  1163. char *addr;
  1164. int retval, addr_len;
  1165. long port = 0;
  1166. int argc = ZEND_NUM_ARGS();
  1167. if (zend_parse_parameters(argc TSRMLS_CC, "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE) {
  1168. return;
  1169. }
  1170. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  1171. switch(php_sock->type) {
  1172. #if HAVE_IPV6
  1173. case AF_INET6: {
  1174. struct sockaddr_in6 sin6 = {0};
  1175. if (argc != 3) {
  1176. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Socket of type AF_INET6 requires 3 arguments");
  1177. RETURN_FALSE;
  1178. }
  1179. memset(&sin6, 0, sizeof(struct sockaddr_in6));
  1180. sin6.sin6_family = AF_INET6;
  1181. sin6.sin6_port = htons((unsigned short int)port);
  1182. if (! php_set_inet6_addr(&sin6, addr, php_sock TSRMLS_CC)) {
  1183. RETURN_FALSE;
  1184. }
  1185. retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin6, sizeof(struct sockaddr_in6));
  1186. break;
  1187. }
  1188. #endif
  1189. case AF_INET: {
  1190. struct sockaddr_in sin = {0};
  1191. if (argc != 3) {
  1192. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Socket of type AF_INET requires 3 arguments");
  1193. RETURN_FALSE;
  1194. }
  1195. sin.sin_family = AF_INET;
  1196. sin.sin_port = htons((unsigned short int)port);
  1197. if (! php_set_inet_addr(&sin, addr, php_sock TSRMLS_CC)) {
  1198. RETURN_FALSE;
  1199. }
  1200. retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
  1201. break;
  1202. }
  1203. case AF_UNIX: {
  1204. struct sockaddr_un s_un = {0};
  1205. if (addr_len >= sizeof(s_un.sun_path)) {
  1206. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Path too long");
  1207. RETURN_FALSE;
  1208. }
  1209. s_un.sun_family = AF_UNIX;
  1210. memcpy(&s_un.sun_path, addr, addr_len);
  1211. retval = connect(php_sock->bsd_socket, (struct sockaddr *) &s_un,
  1212. (socklen_t)(XtOffsetOf(struct sockaddr_un, sun_path) + addr_len));
  1213. break;
  1214. }
  1215. default:
  1216. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported socket type %d", php_sock->type);
  1217. RETURN_FALSE;
  1218. }
  1219. if (retval != 0) {
  1220. PHP_SOCKET_ERROR(php_sock, "unable to connect", errno);
  1221. RETURN_FALSE;
  1222. }
  1223. RETURN_TRUE;
  1224. }
  1225. /* }}} */
  1226. /* {{{ proto string socket_strerror(int errno)
  1227. Returns a string describing an error */
  1228. PHP_FUNCTION(socket_strerror)
  1229. {
  1230. long arg1;
  1231. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &arg1) == FAILURE) {
  1232. return;
  1233. }
  1234. RETURN_STRING(sockets_strerror(arg1 TSRMLS_CC), 1);
  1235. }
  1236. /* }}} */
  1237. /* {{{ proto bool socket_bind(resource socket, string addr [, int port])
  1238. Binds an open socket to a listening port, port is only specified in AF_INET family. */
  1239. PHP_FUNCTION(socket_bind)
  1240. {
  1241. zval *arg1;
  1242. php_sockaddr_storage sa_storage = {0};
  1243. struct sockaddr *sock_type = (struct sockaddr*) &sa_storage;
  1244. php_socket *php_sock;
  1245. char *addr;
  1246. int addr_len;
  1247. long port = 0;
  1248. long retval = 0;
  1249. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE) {
  1250. return;
  1251. }
  1252. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  1253. switch(php_sock->type) {
  1254. case AF_UNIX:
  1255. {
  1256. struct sockaddr_un *sa = (struct sockaddr_un *) sock_type;
  1257. sa->sun_family = AF_UNIX;
  1258. if (addr_len >= sizeof(sa->sun_path)) {
  1259. php_error_docref(NULL TSRMLS_CC, E_WARNING,
  1260. "Invalid path: too long (maximum size is %d)",
  1261. (int)sizeof(sa->sun_path) - 1);
  1262. RETURN_FALSE;
  1263. }
  1264. memcpy(&sa->sun_path, addr, addr_len);
  1265. retval = bind(php_sock->bsd_socket, (struct sockaddr *) sa,
  1266. offsetof(struct sockaddr_un, sun_path) + addr_len);
  1267. break;
  1268. }
  1269. case AF_INET:
  1270. {
  1271. struct sockaddr_in *sa = (struct sockaddr_in *) sock_type;
  1272. sa->sin_family = AF_INET;
  1273. sa->sin_port = htons((unsigned short) port);
  1274. if (! php_set_inet_addr(sa, addr, php_sock TSRMLS_CC)) {
  1275. RETURN_FALSE;
  1276. }
  1277. retval = bind(php_sock->bsd_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in));
  1278. break;
  1279. }
  1280. #if HAVE_IPV6
  1281. case AF_INET6:
  1282. {
  1283. struct sockaddr_in6 *sa = (struct sockaddr_in6 *) sock_type;
  1284. sa->sin6_family = AF_INET6;
  1285. sa->sin6_port = htons((unsigned short) port);
  1286. if (! php_set_inet6_addr(sa, addr, php_sock TSRMLS_CC)) {
  1287. RETURN_FALSE;
  1288. }
  1289. retval = bind(php_sock->bsd_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in6));
  1290. break;
  1291. }
  1292. #endif
  1293. default:
  1294. php_error_docref(NULL TSRMLS_CC, E_WARNING, "unsupported socket type '%d', must be AF_UNIX, AF_INET, or AF_INET6", php_sock->type);
  1295. RETURN_FALSE;
  1296. }
  1297. if (retval != 0) {
  1298. PHP_SOCKET_ERROR(php_sock, "unable to bind address", errno);
  1299. RETURN_FALSE;
  1300. }
  1301. RETURN_TRUE;
  1302. }
  1303. /* }}} */
  1304. /* {{{ proto int socket_recv(resource socket, string &buf, int len, int flags)
  1305. Receives data from a connected socket */
  1306. PHP_FUNCTION(socket_recv)
  1307. {
  1308. zval *php_sock_res, *buf;
  1309. char *recv_buf;
  1310. php_socket *php_sock;
  1311. int retval;
  1312. long len, flags;
  1313. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzll", &php_sock_res, &buf, &len, &flags) == FAILURE) {
  1314. return;
  1315. }
  1316. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &php_sock_res, -1, le_socket_name, le_socket);
  1317. /* overflow check */
  1318. if ((len + 1) < 2) {
  1319. RETURN_FALSE;
  1320. }
  1321. recv_buf = emalloc(len + 1);
  1322. memset(recv_buf, 0, len + 1);
  1323. if ((retval = recv(php_sock->bsd_socket, recv_buf, len, flags)) < 1) {
  1324. efree(recv_buf);
  1325. zval_dtor(buf);
  1326. Z_TYPE_P(buf) = IS_NULL;
  1327. } else {
  1328. recv_buf[retval] = '\0';
  1329. /* Rebuild buffer zval */
  1330. zval_dtor(buf);
  1331. Z_STRVAL_P(buf) = recv_buf;
  1332. Z_STRLEN_P(buf) = retval;
  1333. Z_TYPE_P(buf) = IS_STRING;
  1334. }
  1335. if (retval == -1) {
  1336. PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno);
  1337. RETURN_FALSE;
  1338. }
  1339. RETURN_LONG(retval);
  1340. }
  1341. /* }}} */
  1342. /* {{{ proto int socket_send(resource socket, string buf, int len, int flags)
  1343. Sends data to a connected socket */
  1344. PHP_FUNCTION(socket_send)
  1345. {
  1346. zval *arg1;
  1347. php_socket *php_sock;
  1348. int buf_len, retval;
  1349. long len, flags;
  1350. char *buf;
  1351. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsll", &arg1, &buf, &buf_len, &len, &flags) == FAILURE) {
  1352. return;
  1353. }
  1354. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  1355. retval = send(php_sock->bsd_socket, buf, (buf_len < len ? buf_len : len), flags);
  1356. if (retval == -1) {
  1357. PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);
  1358. RETURN_FALSE;
  1359. }
  1360. RETURN_LONG(retval);
  1361. }
  1362. /* }}} */
  1363. /* {{{ proto int socket_recvfrom(resource socket, string &buf, int len, int flags, string &name [, int &port])
  1364. Receives data from a socket, connected or not */
  1365. PHP_FUNCTION(socket_recvfrom)
  1366. {
  1367. zval *arg1, *arg2, *arg5, *arg6 = NULL;
  1368. php_socket *php_sock;
  1369. struct sockaddr_un s_un;
  1370. struct sockaddr_in sin;
  1371. #if HAVE_IPV6
  1372. struct sockaddr_in6 sin6;
  1373. char addr6[INET6_ADDRSTRLEN];
  1374. #endif
  1375. socklen_t slen;
  1376. int retval;
  1377. long arg3, arg4;
  1378. char *recv_buf, *address;
  1379. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzllz|z", &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) {
  1380. return;
  1381. }
  1382. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  1383. /* overflow check */
  1384. if ((arg3 + 2) < 3) {
  1385. RETURN_FALSE;
  1386. }
  1387. recv_buf = emalloc(arg3 + 2);
  1388. memset(recv_buf, 0, arg3 + 2);
  1389. switch (php_sock->type) {
  1390. case AF_UNIX:
  1391. slen = sizeof(s_un);
  1392. s_un.sun_family = AF_UNIX;
  1393. retval = recvfrom(php_sock->bsd_socket, recv_buf, arg3, arg4, (struct sockaddr *)&s_un, (socklen_t *)&slen);
  1394. if (retval < 0) {
  1395. PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno);
  1396. efree(recv_buf);
  1397. RETURN_FALSE;
  1398. }
  1399. zval_dtor(arg2);
  1400. zval_dtor(arg5);
  1401. ZVAL_STRINGL(arg2, recv_buf, retval, 0);
  1402. ZVAL_STRING(arg5, s_un.sun_path, 1);
  1403. break;
  1404. case AF_INET:
  1405. slen = sizeof(sin);
  1406. memset(&sin, 0, slen);
  1407. sin.sin_family = AF_INET;
  1408. if (arg6 == NULL) {
  1409. efree(recv_buf);
  1410. WRONG_PARAM_COUNT;
  1411. }
  1412. retval = recvfrom(php_sock->bsd_socket, recv_buf, arg3, arg4, (struct sockaddr *)&sin, (socklen_t *)&slen);
  1413. if (retval < 0) {
  1414. PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno);
  1415. efree(recv_buf);
  1416. RETURN_FALSE;
  1417. }
  1418. zval_dtor(arg2);
  1419. zval_dtor(arg5);
  1420. zval_dtor(arg6);
  1421. address = inet_ntoa(sin.sin_addr);
  1422. ZVAL_STRINGL(arg2, recv_buf, retval, 0);
  1423. ZVAL_STRING(arg5, address ? address : "0.0.0.0", 1);
  1424. ZVAL_LONG(arg6, ntohs(sin.sin_port));
  1425. break;
  1426. #if HAVE_IPV6
  1427. case AF_INET6:
  1428. slen = sizeof(sin6);
  1429. memset(&sin6, 0, slen);
  1430. sin6.sin6_family = AF_INET6;
  1431. if (arg6 == NULL) {
  1432. efree(recv_buf);
  1433. WRONG_PARAM_COUNT;
  1434. }
  1435. retval = recvfrom(php_sock->bsd_socket, recv_buf, arg3, arg4, (struct sockaddr *)&sin6, (socklen_t *)&slen);
  1436. if (retval < 0) {
  1437. PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno);
  1438. efree(recv_buf);
  1439. RETURN_FALSE;
  1440. }
  1441. zval_dtor(arg2);
  1442. zval_dtor(arg5);
  1443. zval_dtor(arg6);
  1444. memset(addr6, 0, INET6_ADDRSTRLEN);
  1445. inet_ntop(AF_INET6, &sin6.sin6_addr, addr6, INET6_ADDRSTRLEN);
  1446. ZVAL_STRINGL(arg2, recv_buf, retval, 0);
  1447. ZVAL_STRING(arg5, addr6[0] ? addr6 : "::", 1);
  1448. ZVAL_LONG(arg6, ntohs(sin6.sin6_port));
  1449. break;
  1450. #endif
  1451. default:
  1452. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported socket type %d", php_sock->type);
  1453. RETURN_FALSE;
  1454. }
  1455. RETURN_LONG(retval);
  1456. }
  1457. /* }}} */
  1458. /* {{{ proto int socket_sendto(resource socket, string buf, int len, int flags, string addr [, int port])
  1459. Sends a message to a socket, whether it is connected or not */
  1460. PHP_FUNCTION(socket_sendto)
  1461. {
  1462. zval *arg1;
  1463. php_socket *php_sock;
  1464. struct sockaddr_un s_un;
  1465. struct sockaddr_in sin;
  1466. #if HAVE_IPV6
  1467. struct sockaddr_in6 sin6;
  1468. #endif
  1469. int retval, buf_len, addr_len;
  1470. long len, flags, port = 0;
  1471. char *buf, *addr;
  1472. int argc = ZEND_NUM_ARGS();
  1473. if (zend_parse_parameters(argc TSRMLS_CC, "rslls|l", &arg1, &buf, &buf_len, &len, &flags, &addr, &addr_len, &port) == FAILURE) {
  1474. return;
  1475. }
  1476. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  1477. switch (php_sock->type) {
  1478. case AF_UNIX:
  1479. memset(&s_un, 0, sizeof(s_un));
  1480. s_un.sun_family = AF_UNIX;
  1481. snprintf(s_un.sun_path, 108, "%s", addr);
  1482. retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &s_un, SUN_LEN(&s_un));
  1483. break;
  1484. case AF_INET:
  1485. if (argc != 6) {
  1486. WRONG_PARAM_COUNT;
  1487. }
  1488. memset(&sin, 0, sizeof(sin));
  1489. sin.sin_family = AF_INET;
  1490. sin.sin_port = htons((unsigned short) port);
  1491. if (! php_set_inet_addr(&sin, addr, php_sock TSRMLS_CC)) {
  1492. RETURN_FALSE;
  1493. }
  1494. retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &sin, sizeof(sin));
  1495. break;
  1496. #if HAVE_IPV6
  1497. case AF_INET6:
  1498. if (argc != 6) {
  1499. WRONG_PARAM_COUNT;
  1500. }
  1501. memset(&sin6, 0, sizeof(sin6));
  1502. sin6.sin6_family = AF_INET6;
  1503. sin6.sin6_port = htons((unsigned short) port);
  1504. if (! php_set_inet6_addr(&sin6, addr, php_sock TSRMLS_CC)) {
  1505. RETURN_FALSE;
  1506. }
  1507. retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &sin6, sizeof(sin6));
  1508. break;
  1509. #endif
  1510. default:
  1511. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported socket type %d", php_sock->type);
  1512. RETURN_FALSE;
  1513. }
  1514. if (retval == -1) {
  1515. PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);
  1516. RETURN_FALSE;
  1517. }
  1518. RETURN_LONG(retval);
  1519. }
  1520. /* }}} */
  1521. /* {{{ proto mixed socket_get_option(resource socket, int level, int optname) U
  1522. Gets socket options for the socket */
  1523. PHP_FUNCTION(socket_get_option)
  1524. {
  1525. zval *arg1;
  1526. struct linger linger_val;
  1527. struct timeval tv;
  1528. #ifdef PHP_WIN32
  1529. int timeout = 0;
  1530. #endif
  1531. socklen_t optlen;
  1532. php_socket *php_sock;
  1533. int other_val;
  1534. long level, optname;
  1535. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &arg1, &level, &optname) == FAILURE) {
  1536. return;
  1537. }
  1538. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  1539. if (level == IPPROTO_IP) {
  1540. switch (optname) {
  1541. case IP_MULTICAST_IF: {
  1542. struct in_addr if_addr;
  1543. unsigned int if_index;
  1544. optlen = sizeof(if_addr);
  1545. if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&if_addr, &optlen) != 0) {
  1546. PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
  1547. RETURN_FALSE;
  1548. }
  1549. if (php_add4_to_if_index(&if_addr, php_sock, &if_index TSRMLS_CC) == SUCCESS) {
  1550. RETURN_LONG((long) if_index);
  1551. } else {
  1552. RETURN_FALSE;
  1553. }
  1554. }
  1555. }
  1556. }
  1557. #if HAVE_IPV6
  1558. else if (level == IPPROTO_IPV6) {
  1559. int ret = php_do_getsockopt_ipv6_rfc3542(php_sock, level, optname, return_value TSRMLS_CC);
  1560. if (ret == SUCCESS) {
  1561. return;
  1562. } else if (ret == FAILURE) {
  1563. RETURN_FALSE;
  1564. } /* else continue */
  1565. }
  1566. #endif
  1567. /* sol_socket options and general case */
  1568. switch(optname) {
  1569. case SO_LINGER:
  1570. optlen = sizeof(linger_val);
  1571. if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&linger_val, &optlen) != 0) {
  1572. PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
  1573. RETURN_FALSE;
  1574. }
  1575. array_init(return_value);
  1576. add_assoc_long(return_value, "l_onoff", linger_val.l_onoff);
  1577. add_assoc_long(return_value, "l_linger", linger_val.l_linger);
  1578. break;
  1579. case SO_RCVTIMEO:
  1580. case SO_SNDTIMEO:
  1581. #ifndef PHP_WIN32
  1582. optlen = sizeof(tv);
  1583. if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&tv, &optlen) != 0) {
  1584. PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
  1585. RETURN_FALSE;
  1586. }
  1587. #else
  1588. optlen = sizeof(int);
  1589. if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&timeout, &optlen) != 0) {
  1590. PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
  1591. RETURN_FALSE;
  1592. }
  1593. tv.tv_sec = timeout ? timeout / 1000 : 0;
  1594. tv.tv_usec = timeout ? (timeout * 1000) % 1000000 : 0;
  1595. #endif
  1596. array_init(return_value);
  1597. add_assoc_long(return_value, "sec", tv.tv_sec);
  1598. add_assoc_long(return_value, "usec", tv.tv_usec);
  1599. break;
  1600. default:
  1601. optlen = sizeof(other_val);
  1602. if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&other_val, &optlen) != 0) {
  1603. PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
  1604. RETURN_FALSE;
  1605. }
  1606. if (optlen == 1)
  1607. other_val = *((unsigned char *)&other_val);
  1608. RETURN_LONG(other_val);
  1609. break;
  1610. }
  1611. }
  1612. /* }}} */
  1613. /* {{{ proto bool socket_set_option(resource socket, int level, int optname, int|array optval)
  1614. Sets socket options for the socket */
  1615. PHP_FUNCTION(socket_set_option)
  1616. {
  1617. zval *arg1, **arg4;
  1618. struct linger lv;
  1619. php_socket *php_sock;
  1620. int ov, optlen, retval;
  1621. #ifdef PHP_WIN32
  1622. int timeout;
  1623. #else
  1624. struct timeval tv;
  1625. #endif
  1626. long level, optname;
  1627. void *opt_ptr;
  1628. HashTable *opt_ht;
  1629. zval **l_onoff, **l_linger;
  1630. zval **sec, **usec;
  1631. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllZ", &arg1, &level, &optname, &arg4) == FAILURE) {
  1632. return;
  1633. }
  1634. ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
  1635. set_errno(0);
  1636. #define HANDLE_SUBCALL(res) \
  1637. do { \
  1638. if (res == 1) { goto default_case; } \
  1639. else if (res == SUCCESS) { RETURN_TRUE; } \
  1640. else { RETURN_FALSE; } \
  1641. } while (0)
  1642. if (level == IPPROTO_IP) {
  1643. int res = php_do_setsockopt_ip_mcast(php_sock, level, optname, arg4 TSRMLS_CC);
  1644. HANDLE_SUBCALL(res);
  1645. }
  1646. #if HAVE_IPV6
  1647. else if (level == IPPROTO_IPV6) {
  1648. int res = php_do_setsockopt_ipv6_mcast(php_sock, level, optname, arg4 TSRMLS_CC);
  1649. if (res == 1) {
  1650. res = php_do_setsockopt_ipv6_rfc3542(php_sock, level, optname, arg4 TSRMLS_CC);
  1651. }
  1652. HANDLE_SUBCALL(res);
  1653. }
  1654. #endif
  1655. switch (optname) {
  1656. case SO_LINGER: {
  1657. const char l_onoff_key[] = "l_onoff";
  1658. const char l_linger_key[] = "l_linger";
  1659. convert_to_array_ex(arg4);
  1660. opt_ht = HASH_OF(*arg4);
  1661. if (zend_hash_find(opt_ht, l_onoff_key, sizeof(l_onoff_key), (void **)&l_onoff) == FAILURE) {
  1662. php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", l_onoff_key);
  1663. RETURN_FALSE;
  1664. }
  1665. if (zend_hash_find(opt_ht, l_linger_key, sizeof(l_linger_key), (void **)&l_linger) == FAILURE) {
  1666. php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", l_linger_key);
  1667. RETURN_FALSE;
  1668. }
  1669. convert_to_long_ex(l_onoff);
  1670. convert_to_long_ex(l_linger);
  1671. lv.l_onoff = (unsigned short)Z_LVAL_PP(l_onoff);
  1672. lv.l_linger = (unsigned short)Z_LVAL_PP(l_linger);
  1673. optlen = sizeof(lv);
  1674. opt_ptr = &lv;
  1675. break;
  1676. }
  1677. case SO_RCVTIMEO:
  1678. case SO_SNDTIMEO: {
  1679. const char sec_key[] = "sec";
  1680. const char usec_key[] = "usec";
  1681. convert_to_array_ex(arg4);
  1682. opt_ht = HASH_OF(*arg4);
  1683. if (zend_hash_find(opt_ht, sec_key, sizeof(sec_key), (void **)&sec) == FAILURE) {
  1684. php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", sec_key);
  1685. RETURN_FALSE;
  1686. }
  1687. if (zend_hash_find(opt_ht, usec_key, sizeof(usec_key), (void **)&usec) == FAILURE) {
  1688. php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", usec_key);
  1689. RETURN_FALSE;
  1690. }
  1691. convert_to_long_ex(sec);
  1692. convert_to_long_ex(usec);
  1693. #ifndef PHP_WIN32
  1694. tv.tv_sec = Z_LVAL_PP(sec);
  1695. tv.tv_usec = Z_LVAL_PP(usec);
  1696. optlen = sizeof(tv);
  1697. opt_ptr = &tv;
  1698. #else
  1699. timeout = Z_LVAL_PP(sec) * 1000 + Z_LVAL_PP(usec) / 1000;
  1700. optlen = sizeof(int);
  1701. opt_ptr = &timeout;
  1702. #endif
  1703. break;
  1704. }
  1705. #ifdef SO_BINDTODEVICE
  1706. case SO_BINDTODEVICE: {
  1707. if (Z_TYPE_PP(arg4) == IS_STRING) {
  1708. opt_ptr = Z_STRVAL_PP(arg4);
  1709. optlen = Z_STRLEN_PP(arg4);
  1710. } else {
  1711. opt_ptr = "";
  1712. optlen = 0;
  1713. }
  1714. break;
  1715. }
  1716. #endif
  1717. default:
  1718. default_case:
  1719. convert_to_long_ex(arg4);
  1720. ov = Z_LVAL_PP(arg4);
  1721. optlen = sizeof(ov);
  1722. opt_ptr = &ov;
  1723. break;
  1724. }
  1725. retval = setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen);
  1726. if (retval != 0) {
  1727. PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno);
  1728. RETURN_FALSE;
  1729. }
  1730. RETURN_TRUE;
  1731. }
  1732. /* }}} */
  1733. #ifdef HAVE_SOCKETPAIR
  1734. /* {{{ proto bool socket_create_pair(int domain, int type, int protocol, array &fd) U
  1735. Creates a pair of indistinguishable sockets and stores them in fds. */
  1736. PHP_FUNCTION(socket_create_pair)
  1737. {
  1738. zval *retval[2], *fds_array_zval;
  1739. php_socket *php_sock[2];
  1740. PHP_SOCKET fds_array[2];
  1741. long domain, type, protocol;
  1742. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lllz", &domain, &type, &protocol, &fds_array_zval) == FAILURE) {
  1743. return;
  1744. }
  1745. php_sock[0] = php_create_socket();
  1746. php_sock[1] = php_create_socket();
  1747. if (domain != AF_INET
  1748. #if HAVE_IPV6
  1749. && domain != AF_INET6
  1750. #endif
  1751. && domain != AF_UNIX) {
  1752. php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket domain [%ld] specified for argument 1, assuming AF_INET", domain);
  1753. domain = AF_INET;
  1754. }
  1755. if (type > 10) {
  1756. php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM", type);
  1757. type = SOCK_STREAM;
  1758. }
  1759. if (socketpair(domain, type, protocol, fds_array) != 0) {
  1760. SOCKETS_G(last_error) = errno;
  1761. php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to create socket pair [%d]: %s", errno, sockets_strerror(errno TSRMLS_CC));
  1762. efree(php_sock[0]);
  1763. efree(php_sock[1]);
  1764. RETURN_FALSE;
  1765. }
  1766. zval_dtor(fds_array_zval);
  1767. array_init(fds_array_zval);
  1768. MAKE_STD_ZVAL(retval[0]);
  1769. MAKE_STD_ZVAL(retval[1]);
  1770. php_sock[0]->bsd_socket = fds_array[0];
  1771. php_sock[1]->bsd_socket = fds_array[1];
  1772. php_sock[0]->type = domain;
  1773. php_sock[1]->type = domain;
  1774. php_sock[0]->error = 0;
  1775. php_sock[1]->error = 0;
  1776. php_sock[0]->blocking = 1;
  1777. php_sock[1]->blocking = 1;
  1778. ZEND_REGISTER_RESOURCE(retval[0], php_sock[0], le_socket);
  1779. ZEND_REGISTER_RESOURCE(retval[1], php_sock[1], le_socket);
  1780. add_index_zval(fds_array_zval, 0, retval[0]);
  1781. add_index_zval(fds_array_zval, 1, retval[1]);
  1782. RETURN_TRUE;
  1783. }
  1784. /* }}} */
  1785. #endif
  1786. #ifdef HAVE_SHUTDOWN
  1787. /* {{{ proto bool socket_shutdown(resource socket[, int how]) U
  1788. Shuts down a socket for receiving, sending, or both. */
  1789. PHP_FUNCTION(socket_shutdown)
  1790. {
  1791. zval *arg1;
  1792. long how_shutdown = 2;
  1793. php_socket *php_sock;
  1794. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &arg1, &how_shutdown) == FAILURE) {
  1795. return;
  1796. }
  1797. ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg1, -1, le_socket_name, le_socket);
  1798. if (shutdown(php_sock->bsd_socket, how_shutdown) != 0) {
  1799. PHP_SOCKET_ERROR(php_sock, "unable to shutdown socket", errno);
  1800. RETURN_FALSE;
  1801. }
  1802. RETURN_TRUE;
  1803. }
  1804. /* }}} */
  1805. #endif
  1806. /* {{{ proto int socket_last_error([resource socket]) U
  1807. Returns the last socket error (either the last used or the provided socket resource) */
  1808. PHP_FUNCTION(socket_last_error)
  1809. {
  1810. zval *arg1 = NULL;
  1811. php_socket *php_sock;
  1812. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg1) == FAILURE) {
  1813. return;
  1814. }
  1815. if (arg1) {
  1816. ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg1, -1, le_socket_name, le_socket);
  1817. RETVAL_LONG(php_sock->error);
  1818. } else {
  1819. RETVAL_LONG(SOCKETS_G(last_error));
  1820. }
  1821. }
  1822. /* }}} */
  1823. /* {{{ proto void socket_clear_error([resource socket]) U
  1824. Clears the error on the socket or the last error code. */
  1825. PHP_FUNCTION(socket_clear_error)
  1826. {
  1827. zval *arg1 = NULL;
  1828. php_socket *php_sock;
  1829. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg1) == FAILURE) {
  1830. return;
  1831. }
  1832. if (arg1) {
  1833. ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg1, -1, le_socket_name, le_socket);
  1834. php_sock->error = 0;
  1835. } else {
  1836. SOCKETS_G(last_error) = 0;
  1837. }
  1838. return;
  1839. }
  1840. /* }}} */
  1841. php_socket *socket_import_file_descriptor(PHP_SOCKET socket TSRMLS_DC)
  1842. {
  1843. #ifdef SO_DOMAIN
  1844. int type;
  1845. socklen_t type_len = sizeof(type);
  1846. #endif
  1847. php_socket *retsock;
  1848. php_sockaddr_storage addr;
  1849. socklen_t addr_len = sizeof(addr);
  1850. #ifndef PHP_WIN32
  1851. int t;
  1852. #endif
  1853. retsock = php_create_socket();
  1854. retsock->bsd_socket = socket;
  1855. /* determine family */
  1856. #ifdef SO_DOMAIN
  1857. if (getsockopt(socket, SOL_SOCKET, SO_DOMAIN, &type, &type_len) == 0) {
  1858. retsock->type = type;
  1859. } else
  1860. #endif
  1861. if (getsockname(socket, (struct sockaddr*)&addr, &addr_len) == 0) {
  1862. retsock->type = addr.ss_family;
  1863. } else {
  1864. PHP_SOCKET_ERROR(retsock, "unable to obtain socket family", errno);
  1865. goto error;
  1866. }
  1867. /* determine blocking mode */
  1868. #ifndef PHP_WIN32
  1869. t = fcntl(socket, F_GETFL);
  1870. if (t == -1) {
  1871. PHP_SOCKET_ERROR(retsock, "unable to obtain blocking state", errno);
  1872. goto error;
  1873. } else {
  1874. retsock->blocking = !(t & O_NONBLOCK);
  1875. }
  1876. #endif
  1877. return retsock;
  1878. error:
  1879. efree(retsock);
  1880. return NULL;
  1881. }
  1882. /* {{{ proto void socket_import_stream(resource stream)
  1883. Imports a stream that encapsulates a socket into a socket extension resource. */
  1884. PHP_FUNCTION(socket_import_stream)
  1885. {
  1886. zval *zstream;
  1887. php_stream *stream;
  1888. php_socket *retsock = NULL;
  1889. PHP_SOCKET socket; /* fd */
  1890. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) == FAILURE) {
  1891. return;
  1892. }
  1893. php_stream_from_zval(stream, &zstream);
  1894. if (php_stream_cast(stream, PHP_STREAM_AS_SOCKETD, (void**)&socket, 1)) {
  1895. /* error supposedly already shown */
  1896. RETURN_FALSE;
  1897. }
  1898. retsock = socket_import_file_descriptor(socket TSRMLS_CC);
  1899. if (retsock == NULL) {
  1900. RETURN_FALSE;
  1901. }
  1902. #ifdef PHP_WIN32
  1903. /* on windows, check if the stream is a socket stream and read its
  1904. * private data; otherwise assume it's in non-blocking mode */
  1905. if (php_stream_is(stream, PHP_STREAM_IS_SOCKET)) {
  1906. retsock->blocking =
  1907. ((php_netstream_data_t *)stream->abstract)->is_blocked;
  1908. } else {
  1909. retsock->blocking = 1;
  1910. }
  1911. #endif
  1912. /* hold a zval reference to the stream (holding a php_stream* directly could
  1913. * also be done, but this might be slightly better if in the future we want
  1914. * to provide a socket_export_stream) */
  1915. MAKE_STD_ZVAL(retsock->zstream);
  1916. *retsock->zstream = *zstream;
  1917. zval_copy_ctor(retsock->zstream);
  1918. Z_UNSET_ISREF_P(retsock->zstream);
  1919. Z_SET_REFCOUNT_P(retsock->zstream, 1);
  1920. php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER,
  1921. PHP_STREAM_BUFFER_NONE, NULL);
  1922. ZEND_REGISTER_RESOURCE(return_value, retsock, le_socket);
  1923. }
  1924. /* }}} */
  1925. /*
  1926. * Local variables:
  1927. * tab-width: 4
  1928. * c-basic-offset: 4
  1929. * End:
  1930. * vim600: fdm=marker
  1931. * vim: noet sw=4 ts=4
  1932. */