Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
4.3 KiB

  1. /*
  2. see copyright notice in sqrdbg.h
  3. */
  4. #include "tier0/basetypes.h"
  5. #include <squirrel.h>
  6. #if !defined( _X360 ) && !defined( _PS3 ) && !defined( POSIX )
  7. #include <winsock.h>
  8. #endif
  9. #include "sqrdbg.h"
  10. #include "sqdbgserver.h"
  11. SQInteger debug_hook(HSQUIRRELVM v);
  12. SQInteger error_handler(HSQUIRRELVM v);
  13. #include "serialize_state.inl"
  14. #if defined(VSCRIPT_DLL_EXPORT) || defined(VSQUIRREL_TEST)
  15. #include "memdbgon.h"
  16. #endif
  17. HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate)
  18. {
  19. #ifndef _GAMECONSOLE
  20. sockaddr_in bindaddr;
  21. #ifdef _WIN32
  22. WSADATA wsadata;
  23. if (WSAStartup (MAKEWORD(1,1), &wsadata) != 0){
  24. return NULL;
  25. }
  26. #endif
  27. SQDbgServer *rdbg = new SQDbgServer(v);
  28. rdbg->_autoupdate = autoupdate?true:false;
  29. rdbg->_accept = socket(AF_INET,SOCK_STREAM,0);
  30. bindaddr.sin_family = AF_INET;
  31. bindaddr.sin_port = htons(port);
  32. bindaddr.sin_addr.s_addr = htonl (INADDR_ANY);
  33. if(bind(rdbg->_accept,(sockaddr*)&bindaddr,sizeof(bindaddr))==SOCKET_ERROR){
  34. delete rdbg;
  35. sq_throwerror(v,_SC("failed to bind the socket"));
  36. return NULL;
  37. }
  38. if(!rdbg->Init()) {
  39. delete rdbg;
  40. sq_throwerror(v,_SC("failed to initialize the debugger"));
  41. return NULL;
  42. }
  43. return rdbg;
  44. #else
  45. return NULL;
  46. #endif
  47. }
  48. SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg)
  49. {
  50. #ifndef _GAMECONSOLE
  51. if(SQ_FAILED(sq_compilebuffer(rdbg->_v,serialize_state_nut,(SQInteger)scstrlen(serialize_state_nut),_SC("SERIALIZE_STATE"),SQFalse))) {
  52. sq_throwerror(rdbg->_v,_SC("error compiling the serialization function"));
  53. }
  54. sq_getstackobj(rdbg->_v,-1,&rdbg->_serializefunc);
  55. sq_addref(rdbg->_v,&rdbg->_serializefunc);
  56. sq_pop(rdbg->_v,1);
  57. sockaddr_in cliaddr;
  58. int addrlen=sizeof(cliaddr);
  59. if(listen(rdbg->_accept,0)==SOCKET_ERROR)
  60. return sq_throwerror(rdbg->_v,_SC("error on listen(socket)"));
  61. rdbg->_endpoint = accept(rdbg->_accept,(sockaddr*)&cliaddr,(socklen_t *)&addrlen);
  62. //do not accept any other connection
  63. sqdbg_closesocket(rdbg->_accept);
  64. rdbg->_accept = INVALID_SOCKET;
  65. if(rdbg->_endpoint==INVALID_SOCKET){
  66. return sq_throwerror(rdbg->_v,_SC("error accept(socket)"));
  67. }
  68. while(!rdbg->_ready){
  69. sq_rdbg_update(rdbg);
  70. }
  71. #endif
  72. return SQ_OK;
  73. }
  74. SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg)
  75. {
  76. #ifndef _GAMECONSOLE
  77. #ifdef _WIN32
  78. TIMEVAL time;
  79. #else
  80. struct timeval time;
  81. #endif
  82. time.tv_sec=0;
  83. time.tv_usec=0;
  84. fd_set read_flags;
  85. FD_ZERO(&read_flags);
  86. FD_SET(rdbg->_endpoint, &read_flags);
  87. select(NULL/*ignored*/, &read_flags, NULL, NULL, &time);
  88. if(FD_ISSET(rdbg->_endpoint,&read_flags)){
  89. char temp[1024];
  90. int size=0;
  91. char c,prev=NULL;
  92. memset(&temp,0,sizeof(temp));
  93. int res;
  94. FD_CLR(rdbg->_endpoint, &read_flags);
  95. while((res = recv(rdbg->_endpoint,&c,1,0))>0){
  96. if(c=='\n')break;
  97. if(c!='\r'){
  98. temp[size]=c;
  99. prev=c;
  100. size++;
  101. }
  102. }
  103. switch(res){
  104. case 0:
  105. return sq_throwerror(rdbg->_v,_SC("disconnected"));
  106. case SOCKET_ERROR:
  107. return sq_throwerror(rdbg->_v,_SC("socket error"));
  108. }
  109. temp[size]=NULL;
  110. temp[size+1]=NULL;
  111. rdbg->ParseMsg(temp);
  112. }
  113. #endif
  114. return SQ_OK;
  115. }
  116. SQInteger debug_hook(HSQUIRRELVM v)
  117. {
  118. SQUserPointer up;
  119. intp event_type,line;
  120. const SQChar *src,*func;
  121. sq_getinteger(v,2,&event_type);
  122. sq_getstring(v,3,&src);
  123. sq_getinteger(v,4,&line);
  124. sq_getstring(v,5,&func);
  125. sq_getuserpointer(v,-1,&up);
  126. HSQREMOTEDBG rdbg = (HSQREMOTEDBG)up;
  127. rdbg->Hook(event_type,line,src,func);
  128. if(rdbg->_autoupdate) {
  129. if(SQ_FAILED(sq_rdbg_update(rdbg)))
  130. return sq_throwerror(v,_SC("socket failed"));
  131. }
  132. return 0;
  133. }
  134. SQInteger error_handler(HSQUIRRELVM v)
  135. {
  136. SQUserPointer up;
  137. const SQChar *sErr=NULL;
  138. const SQChar *fn=_SC("unknown");
  139. const SQChar *src=_SC("unknown");
  140. int line=-1;
  141. SQStackInfos si;
  142. sq_getuserpointer(v,-1,&up);
  143. HSQREMOTEDBG rdbg=(HSQREMOTEDBG)up;
  144. if(SQ_SUCCEEDED(sq_stackinfos(v,1,&si)))
  145. {
  146. if(si.funcname)fn=si.funcname;
  147. if(si.source)src=si.source;
  148. line=si.line;
  149. scprintf(_SC("*FUNCTION [%s] %s line [%d]\n"),fn,src,si.line);
  150. }
  151. if(sq_gettop(v)>=1){
  152. if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) {
  153. scprintf(_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr);
  154. rdbg->Break(si.line,src,_SC("error"),sErr);
  155. }
  156. else{
  157. scprintf(_SC("\nAN ERROR HAS OCCURED [unknown]\n"));
  158. rdbg->Break(si.line,src,_SC("error"),_SC("unknown"));
  159. }
  160. }
  161. rdbg->BreakExecution();
  162. return 0;
  163. }
  164. SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg)
  165. {
  166. #ifndef _GAMECONSOLE
  167. delete rdbg;
  168. #ifdef _WIN32
  169. WSACleanup();
  170. #endif
  171. #endif
  172. return SQ_OK;
  173. }