├── .gitignore ├── README.md ├── client ├── ios │ ├── Log.h │ ├── STMClient.h │ ├── STMClient.m │ ├── STMContentProtocol.h │ ├── STMDefaultContentProtocol.h │ ├── STMDefaultContentProtocol.m │ ├── STMNet.h │ ├── STMNet.mm │ ├── STMResponse.h │ ├── STMResponse.m │ ├── compile │ │ ├── Makefile.am │ │ ├── autogen.sh │ │ └── configure.ac │ ├── ios-sdk │ │ └── ios-sdk │ │ │ └── main.m │ ├── out │ │ ├── STMClient.h │ │ └── release │ │ │ └── libstmclient.a │ └── test-stm │ │ ├── test-stm.xcodeproj │ │ └── xcuserdata │ │ │ └── xpwu.xcuserdatad │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ │ ├── test-stm │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── ViewController.h │ │ ├── ViewController.mm │ │ └── main.m │ │ ├── test-stmTests │ │ ├── Info.plist │ │ └── test_stmTests.m │ │ └── test-stmUITests │ │ ├── Info.plist │ │ └── test_stmUITests.m ├── java │ ├── .idea │ │ ├── codeStyles │ │ │ └── Project.xml │ │ └── vcs.xml │ ├── out │ │ └── artifacts │ │ │ └── stm_client │ │ │ └── stm.client.jar │ ├── projectFilesBackup │ │ └── .idea │ │ │ └── workspace.xml │ ├── src │ │ └── stm │ │ │ ├── .idea │ │ │ ├── .gitignore │ │ │ ├── misc.xml │ │ │ ├── modules.xml │ │ │ └── vcs.xml │ │ │ ├── Client.java │ │ │ ├── ContentProtocol.java │ │ │ ├── DefaultContentProtocol.java │ │ │ ├── Net.java │ │ │ └── Response.java │ └── test │ │ ├── META-INF │ │ └── MANIFEST.MF │ │ ├── Main.java │ │ └── MainThreadLooper.java ├── js │ ├── .idea │ │ ├── js.iml │ │ └── modules.xml │ ├── dest │ │ ├── stm.client.extern.js │ │ ├── stm.client.js │ │ ├── stm.client.min.js │ │ └── stringview.min.js │ ├── gulpfile.js │ ├── stm.client.extern.js │ ├── stm.client.js │ ├── stm.contentprotocol.js │ ├── stm.defaultcontentprotocol.js │ ├── stm.response.js │ ├── stringview.js │ └── test │ │ ├── jquery.min.js │ │ ├── test.html │ │ ├── test.min.html │ │ └── test.ssl.html └── wxapp │ ├── .idea │ ├── markdown-navigator │ │ └── profiles_settings.xml │ └── vcs.xml │ ├── app.js │ ├── app.json │ ├── app.wxss │ ├── pages │ ├── index.js │ ├── index.json │ ├── index.wxml │ └── index.wxss │ ├── project.config.json │ └── stm │ ├── client.es6.js │ ├── client.js │ ├── contentprotocol.js │ ├── defaultcontentprotocol.js │ ├── response.js │ ├── stringview.js │ └── wxwebsocket.js ├── nginx.conf ├── push └── php │ ├── CloseConnectionPusher.inc │ ├── DataPusher.inc │ ├── PushState.inc │ ├── Pusher.inc │ ├── testCloseConnectionPusher.php │ └── testDataPusher.php └── stream_module ├── ngx_stream_request_core_module ├── config ├── ngx_radix64_tree.c ├── ngx_radix64_tree.h ├── ngx_str_str_rbtree.c ├── ngx_str_str_rbtree.h ├── ngx_stream_request.c ├── ngx_stream_request.h ├── ngx_stream_request_core_module.c ├── ngx_stream_request_script.c ├── ngx_stream_request_script.h ├── ngx_stream_request_upstream.c ├── ngx_stream_request_upstream.h ├── ngx_stream_request_variables.c └── ngx_stream_request_variables.h ├── ngx_stream_request_cut_frame_module ├── config └── ngx_stream_request_cut_frame_module.c ├── ngx_stream_request_fake_http_module ├── config └── ngx_stream_request_fake_http_module.c ├── ngx_stream_request_http_proxy_module ├── config └── ngx_stream_request_http_proxy_module.c ├── ngx_stream_request_lencontent_module ├── config └── ngx_stream_request_lencontent_module.c ├── ngx_stream_request_push_close_session_module ├── config └── ngx_stream_request_push_close_session_module.c ├── ngx_stream_request_push_data_module ├── config └── ngx_stream_request_push_data_module.c ├── ngx_stream_request_push_module ├── config ├── ngx_stream_request_push_module.c └── ngx_stream_request_push_module.h ├── ngx_stream_request_set_module ├── config └── ngx_stream_request_set_module.c └── ngx_stream_request_websocket_module ├── config └── ngx_stream_request_websocket_module.c /.gitignore: -------------------------------------------------------------------------------- 1 | client/js/.idea/workspace.xml 2 | 3 | client/js/.idea/workspace.xml 4 | 5 | client/ts 6 | 7 | *.class 8 | 9 | client/ios/ios-sdk/ios-sdk.xcodeproj/project.pbxproj 10 | 11 | client/ios/ios-sdk/ios-sdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata 12 | 13 | client/ios/ios-sdk/ios-sdk.xcodeproj/project.xcworkspace/xcuserdata/xpwu.xcuserdatad/UserInterfaceState.xcuserstate 14 | 15 | client/ios/ios-sdk/ios-sdk.xcodeproj/xcuserdata/xpwu.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 16 | 17 | client/ios/ios-sdk/ios-sdk.xcodeproj/xcuserdata/xpwu.xcuserdatad/xcschemes/ios-sdk copy.xcscheme 18 | 19 | client/ios/ios-sdk/ios-sdk.xcodeproj/xcuserdata/xpwu.xcuserdatad/xcschemes/ios-sdk.xcscheme 20 | 21 | client/ios/ios-sdk/ios-sdk.xcodeproj/xcuserdata/xpwu.xcuserdatad/xcschemes/xcschememanagement.plist 22 | 23 | client/java/.idea/compiler.xml 24 | 25 | client/java/.idea/copyright/profiles_settings.xml 26 | 27 | client/java/.idea/description.html 28 | 29 | client/java/.idea/misc.xml 30 | 31 | client/java/.idea/modules.xml 32 | 33 | client/java/.idea/project-template.xml 34 | 35 | client/java/.idea/uiDesigner.xml 36 | 37 | client/java/.idea/workspace.xml 38 | 39 | client/java/stmjava.iml 40 | 41 | client/js/node_modules/ 42 | 43 | client/js/node_modules/clone-buffer/index.js 44 | 45 | client/js/node_modules/clone-buffer/LICENSE 46 | 47 | client/js/node_modules/clone-buffer/package.json 48 | 49 | client/js/node_modules/clone-buffer/README.md 50 | 51 | client/js/node_modules/cloneable-readable/.npmignore 52 | 53 | client/js/node_modules/cloneable-readable/.travis.yml 54 | 55 | client/js/node_modules/cloneable-readable/example.js 56 | 57 | client/js/node_modules/cloneable-readable/index.js 58 | 59 | client/js/node_modules/cloneable-readable/LICENSE 60 | 61 | client/java/.idea/artifacts/stm_client.xml 62 | 63 | client/java/.idea/artifacts/stm_test.xml 64 | 65 | client/java/out/test/stmjava/META-INF/MANIFEST.MF 66 | 67 | client/java/out/artifacts/stm_test/stm.test.jar 68 | 69 | client/ios/compile/.deps/ 70 | 71 | client/ios/compile/.deps/libclient_arm64_a-STMDefaultContentProtocol.Po 72 | 73 | client/ios/compile/.deps/libclient_arm64_a-STMNet.Po 74 | 75 | client/ios/compile/.deps/libclient_arm64_a-STMResponse.Po 76 | 77 | client/ios/compile/autom4te.cache 78 | 79 | client/ios/compile/aclocal.m4 80 | 81 | client/ios/compile/AUTHORS 82 | 83 | client/ios/compile/ChangeLog 84 | 85 | client/ios/compile/compile 86 | 87 | client/ios/compile/config.log 88 | 89 | client/ios/compile/config.status 90 | 91 | client/ios/compile/configure 92 | 93 | client/ios/compile/COPYING 94 | 95 | client/ios/compile/depcomp 96 | 97 | client/ios/compile/INSTALL 98 | 99 | client/ios/compile/install-sh 100 | 101 | client/ios/compile/*.o 102 | 103 | client/ios/compile/*.a 104 | 105 | client/ios/compile/Makefile 106 | 107 | client/ios/compile/Makefile.in 108 | 109 | client/ios/compile/missing 110 | 111 | client/ios/compile/NEWS 112 | 113 | client/ios/compile/README 114 | 115 | push/php/.idea 116 | 117 | .README.md.swp 118 | 119 | client/ts/.idea 120 | 121 | client/js/test/test.11deyi.html 122 | 123 | client/wxapp/.idea/modules.xml 124 | 125 | client/wxapp/.idea/misc.xml 126 | 127 | client/wxapp/.idea/workspace.xml 128 | 129 | client/wxapp/.idea/wxapp.iml 130 | 131 | .DS_Store 132 | 133 | client/js/test/test.jiba.html 134 | 135 | stream_module.tar 136 | 137 | client/js/.idea/misc.xml 138 | 139 | client/js/.idea/misc.xml 140 | 141 | client/js/.idea/misc.xml 142 | 143 | client/js/.idea/watcherTasks.xml 144 | 145 | client/js/.idea/misc.xml 146 | 147 | client/wxapp/.idea/jsLibraryMappings.xml 148 | 149 | client/wxapp/.idea/watcherTasks.xml 150 | 151 | client/js/.idea/misc.xml 152 | 153 | *.pbxproj 154 | 155 | client/ios/test-stm/test-stm.xcodeproj/project.xcworkspace/contents.xcworkspacedata 156 | 157 | client/ios/test-stm/test-stm.xcodeproj/project.xcworkspace/xcuserdata/xpwu.xcuserdatad/IDEFindNavigatorScopes.plist 158 | 159 | client/ios/test-stm/test-stm.xcodeproj/project.xcworkspace/xcuserdata/xpwu.xcuserdatad/UserInterfaceState.xcuserstate 160 | 161 | client/ios/test-stm/test-stm.xcodeproj/xcuserdata/xpwu.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 162 | 163 | client/ios/test-stm/test-stm.xcodeproj/xcuserdata/xpwu.xcuserdatad/xcschemes/test-stm.xcscheme 164 | client/js/.idea/vcs.xml 165 | push/php/anywithyou-dev 166 | -------------------------------------------------------------------------------- /client/ios/Log.h: -------------------------------------------------------------------------------- 1 | // 2 | // Log.h 3 | // ios-sdk 4 | // 5 | // Created by xpwu on 2016/12/2. 6 | // Copyright © 2016年 xpwu.xpwu. All rights reserved. 7 | // 8 | 9 | #ifndef Log_h 10 | #define Log_h 11 | 12 | #ifdef NDEBUG 13 | 14 | #define NSLog(...){} 15 | 16 | #endif 17 | 18 | #endif /* Log_h */ 19 | -------------------------------------------------------------------------------- /client/ios/STMClient.h: -------------------------------------------------------------------------------- 1 | // 2 | // STMClient.h 3 | // ios-sdk 4 | // 5 | // Created by xpwu on 2016/11/24. 6 | // Copyright © 2016年 xpwu.xpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface STMClient : NSObject 12 | 13 | @property(nonatomic) void (^onpush)(NSData*); 14 | 15 | // unit: s 16 | // default 30s; 4*60s; 10s 17 | -(void)setConfigConnectionTimeout:(NSTimeInterval)ctime_s 18 | heartbeat:(NSTimeInterval)htime_s 19 | transmission:(NSTimeInterval)ttime_s; 20 | 21 | 22 | -(void)setConnectHost:(NSString*)host 23 | port:(uint16_t)port; 24 | 25 | -(void)setConnectHost:(NSString*)host 26 | port:(uint16_t)port 27 | onSuccess:(void (^)(void))suc; 28 | 29 | -(void)setConnectHost:(NSString*)host 30 | port:(uint16_t)port 31 | onSuccess:(void (^)(void))suc 32 | onFailed:(void (^)(NSString*))failed; 33 | 34 | 35 | /** 36 | All args can be set nil; 37 | onSuccess: only callback for successful. 38 | onFailed: only callback for failed 39 | complete: callback wether successful or failed 40 | */ 41 | 42 | -(void)addRequestBody:(NSData*)body 43 | onSuccess:(void (^)(NSData*))suc; 44 | 45 | -(void)addRequestBody:(NSData*)body 46 | headers:(NSDictionary*)headers 47 | onSuccess:(void (^)(NSData*))suc; 48 | 49 | -(void)addRequestBody:(NSData*)body 50 | headers:(NSDictionary*)headers 51 | onSuccess:(void (^)(NSData*))suc 52 | onFailed:(void (^)(NSString*))failed; 53 | 54 | -(void)addRequestBody:(NSData*)body 55 | headers:(NSDictionary*)headers 56 | onSuccess:(void (^)(NSData*))suc 57 | onFailed:(void (^)(NSString*))failed 58 | onComplete:(void (^)())complete; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /client/ios/STMClient.m: -------------------------------------------------------------------------------- 1 | // 2 | // STMClient.m 3 | // ios-sdk 4 | // 5 | // Created by xpwu on 2016/11/24. 6 | // Copyright © 2016年 xpwu.xpwu. All rights reserved. 7 | // 8 | 9 | #import "STMClient.h" 10 | #import "STMNet.h" 11 | #import "STMDefaultContentProtocol.h" 12 | #import "Log.h" 13 | 14 | const uint32_t reqIDstart = 200; 15 | const uint32_t pushID = 1; // need equal server 16 | 17 | @interface Request : NSObject 18 | @property(nonatomic) uint32_t reqID; 19 | @property(nonatomic) NSData* body; 20 | @property(nonatomic) NSDictionary* headers; 21 | @property(nonatomic) void (^suc)(NSData*); 22 | @property(nonatomic) BOOL (^sucOnlyForBlock)(NSData*); 23 | @property(nonatomic) void (^failed)(NSString*); 24 | @property(nonatomic) void (^complete)(); 25 | @end 26 | 27 | @implementation Request @end 28 | 29 | @interface STMClient () { 30 | STMNet* net_; 31 | NSMutableDictionary* requests_; 32 | id protocol_; 33 | 34 | uint32_t reqID_; 35 | 36 | void (^onConnectionSuc_)(void); 37 | void (^onConnectionFaild_)(NSString*); 38 | 39 | void (^normalOnMessage_)(NSData*); 40 | 41 | NSTimeInterval ctime_; 42 | NSTimeInterval htime_; 43 | NSTimeInterval ttime_; 44 | } 45 | -(uint32_t)reqID; 46 | -(void)connect; 47 | -(void)postMessage:(void(^)(void))message; 48 | -(void)performMessageByRunLoop_:(id)message; 49 | -(void)sendAllRequests; 50 | -(void)setOnMessageToNormal; 51 | -(void)sendRequest:(NSData*)body 52 | withHeader:(NSDictionary*)header 53 | andReqID:(uint32_t)reqid; 54 | -(void)errorAllRequests:(NSString*)error; 55 | @end 56 | 57 | @implementation STMClient 58 | -(instancetype)init { 59 | if (self = [super init]) { 60 | reqID_ = reqIDstart; 61 | net_ = nil; 62 | protocol_ = [[STMDefaultContentProtocol alloc]init]; 63 | self.onpush = ^(NSData* data){NSLog(@"receive push data");}; 64 | requests_ = [[NSMutableDictionary alloc]init]; 65 | 66 | ctime_ = 30; 67 | htime_ = 4*60; 68 | ttime_ = 10; 69 | } 70 | return self; 71 | } 72 | 73 | -(void)dealloc { 74 | [net_ close]; 75 | } 76 | 77 | -(void)setConfigConnectionTimeout:(NSTimeInterval)ctime 78 | heartbeat:(NSTimeInterval)htime 79 | transmission:(NSTimeInterval)ttime { 80 | ctime_ = ctime; 81 | htime_ = htime; 82 | ttime_ = ttime; 83 | } 84 | 85 | -(void)setConnectHost:(NSString*)host 86 | port:(uint16_t)port { 87 | [self setConnectHost:host port:port onSuccess:nil onFailed:nil]; 88 | } 89 | 90 | -(void)setConnectHost:(NSString*)host 91 | port:(uint16_t)port 92 | onSuccess:(void (^)(void))suc { 93 | [self setConnectHost:host port:port onSuccess:suc onFailed:nil]; 94 | } 95 | 96 | -(void)setConnectHost:(NSString*)host 97 | port:(uint16_t)port 98 | onSuccess:(void (^)(void))suc 99 | onFailed:(void (^)(NSString*))failed { 100 | net_ = [[STMNet alloc]initWithHost:host andPort:port]; 101 | onConnectionSuc_ = suc; 102 | onConnectionFaild_ = failed; 103 | net_.hearbeatTime = htime_; 104 | net_.transmissionTimeout = ttime_; 105 | net_.openTimeout = ctime_; 106 | } 107 | 108 | -(void)addRequestBody:(NSData*)body 109 | onSuccess:(void (^)(NSData*))suc { 110 | [self addRequestBody:body headers:nil onSuccess:suc onFailed:nil onComplete:nil]; 111 | } 112 | 113 | -(void)addRequestBody:(NSData*)body 114 | headers:(NSDictionary*)headers 115 | onSuccess:(void (^)(NSData*))suc { 116 | [self addRequestBody:body headers:headers onSuccess:suc onFailed:nil onComplete:nil]; 117 | } 118 | 119 | -(void)addRequestBody:(NSData*)body 120 | headers:(NSDictionary*)headers 121 | onSuccess:(void (^)(NSData*))suc 122 | onFailed:(void (^)(NSString*))failed { 123 | [self addRequestBody:body headers:headers onSuccess:suc onFailed:failed onComplete:nil]; 124 | } 125 | 126 | -(void)addRequestBody:(NSData*)body 127 | headers:(NSDictionary*)headers 128 | onSuccess:(void (^)(NSData*))suc 129 | onFailed:(void (^)(NSString*))failed 130 | onComplete:(void (^)())complete { 131 | if (net_ == nil) { 132 | if (complete != nil) { 133 | complete(); 134 | } 135 | if (failed != nil) { 136 | failed(@"host and port not set!"); 137 | } 138 | return; 139 | } 140 | 141 | uint32_t reqid = [self reqID]; 142 | Request* req = [[Request alloc]init]; 143 | req.body = body; 144 | req.headers = headers; 145 | req.suc = suc; 146 | req.failed = failed; 147 | req.complete = complete; 148 | req.reqID = reqid; 149 | 150 | [requests_ setObject:req forKey:[NSNumber numberWithInt:reqid]]; 151 | 152 | if (net_.status == STMNetStatusOpen) { 153 | [self sendRequest:body withHeader:headers andReqID:reqid]; 154 | return; 155 | } 156 | if (net_.status == STMNetStatusConnecting) { 157 | return; 158 | } 159 | [self connect]; 160 | } 161 | 162 | #pragma mark - private 163 | 164 | -(uint32_t)reqID { 165 | reqID_ = reqID_+1; 166 | 167 | if (reqID_ < reqIDstart) { 168 | reqID_ = reqIDstart; 169 | } 170 | 171 | return reqID_; 172 | } 173 | 174 | #define defineWEAK(arg) __weak __typeof(arg) _weak_##arg = arg 175 | #define defineWEAK_TYPE(type, arg) type _weak_##arg = arg 176 | #define weak(arg) _weak_##arg 177 | 178 | -(void)connect { 179 | defineWEAK(protocol_); 180 | defineWEAK(self); 181 | defineWEAK(requests_); 182 | 183 | normalOnMessage_ = ^(NSData* data){ 184 | STMResponse* response = [weak(protocol_) parse:data]; 185 | 186 | if (response.reqID == pushID) { 187 | weak(self).onpush(response.data); 188 | return; 189 | } 190 | 191 | Request* request = [weak(requests_) objectForKey:[NSNumber numberWithInt:response.reqID]]; 192 | if (request == nil) { 193 | NSLog(@"error: not find request"); 194 | return; 195 | } 196 | if (request.complete != nil) { 197 | request.complete(); 198 | } 199 | if (response.status != STMResponseStatusSuccess 200 | && request.failed != nil) { 201 | if (response.data == nil) { 202 | request.failed(@"may be server error, but server has closed the error log"); 203 | } else { 204 | request.failed([[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding]); 205 | } 206 | } 207 | if (response.status == STMResponseStatusSuccess 208 | && request.suc != nil) { 209 | request.suc(response.data); 210 | } 211 | 212 | [weak(requests_) removeObjectForKey:[NSNumber numberWithInt:response.reqID]]; 213 | }; 214 | 215 | defineWEAK(onConnectionSuc_); 216 | 217 | net_.onopen = ^(){ 218 | [weak(protocol_) onopen:^{ 219 | [weak(self) sendAllRequests]; 220 | }]; 221 | if (weak(onConnectionSuc_) != nil) { 222 | weak(onConnectionSuc_)(); 223 | } 224 | }; 225 | 226 | defineWEAK(onConnectionFaild_); 227 | 228 | net_.onclose = ^(NSString* str){ 229 | [weak(self) errorAllRequests:str]; 230 | 231 | if (weak(onConnectionFaild_) != nil) { 232 | weak(onConnectionFaild_)(str); 233 | } 234 | }; 235 | 236 | net_.onmessage = normalOnMessage_; 237 | 238 | [net_ open]; 239 | } 240 | 241 | -(void)postMessage:(void(^)(void))message { 242 | STMClient* __weak _self = self; 243 | [[NSRunLoop currentRunLoop]performSelector:@selector(performMessageByRunLoop_:) 244 | target:_self 245 | argument:message 246 | order:0 247 | modes:@[[NSRunLoop currentRunLoop].currentMode]]; 248 | } 249 | 250 | -(void)performMessageByRunLoop_:(id)message { 251 | void(^msg)(void) = message; 252 | msg(); 253 | } 254 | 255 | -(void)sendAllRequests { 256 | defineWEAK(self); 257 | 258 | [requests_ enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key 259 | , Request * _Nonnull obj 260 | , BOOL * _Nonnull stop) { 261 | [weak(self) sendRequest:obj.body withHeader:obj.headers andReqID:obj.reqID]; 262 | }]; 263 | } 264 | 265 | -(void)setOnMessageToNormal { 266 | net_.onmessage = normalOnMessage_; 267 | } 268 | 269 | -(void)sendRequest:(NSData*)body 270 | withHeader:(NSDictionary*)header 271 | andReqID:(uint32_t)reqid { 272 | 273 | NSData* data = [protocol_ build:body 274 | withHeaders:header 275 | withReqID:reqid]; 276 | 277 | if (data == nil) { 278 | [self postMessage:^{ 279 | net_.onmessage([protocol_ buildFailedMessage:@"build message error, maybe length of headers' key or value > 255, or is not asscii" 280 | withReqid:reqid]); 281 | }]; 282 | return; 283 | } 284 | 285 | [net_ send:data]; 286 | } 287 | 288 | -(void)errorAllRequests:(NSString*)error { 289 | [requests_ enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key 290 | , Request * _Nonnull obj 291 | , BOOL * _Nonnull stop) { 292 | normalOnMessage_([protocol_ buildFailedMessage:error 293 | withReqid:[key intValue]]); 294 | }]; 295 | 296 | [requests_ removeAllObjects]; 297 | } 298 | 299 | @end 300 | 301 | 302 | 303 | 304 | -------------------------------------------------------------------------------- /client/ios/STMContentProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // STMContentProtocol.h 3 | // ios-sdk 4 | // 5 | // Created by xpwu on 2016/11/24. 6 | // Copyright © 2016年 xpwu.xpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "STMResponse.h" 11 | 12 | @protocol STMContentProtocol 13 | 14 | -(void)onopen:(void (^)(void))callback; 15 | -(void)onclose; 16 | -(STMResponse*)parse:(NSData*)message; 17 | -(NSData*)build:(NSData*)body 18 | withHeaders:(NSDictionary*)headers 19 | withReqID:(uint32_t)reqID; 20 | 21 | -(NSData*)buildFailedMessage:(NSString*)error withReqid:(uint32_t)reqID; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /client/ios/STMDefaultContentProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // STMDefaultContentProtocol.h 3 | // ios-sdk 4 | // 5 | // Created by xpwu on 2016/11/24. 6 | // Copyright © 2016年 xpwu.xpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "STMContentProtocol.h" 11 | 12 | @interface STMDefaultContentProtocol : NSObject 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /client/ios/STMDefaultContentProtocol.m: -------------------------------------------------------------------------------- 1 | // 2 | // STMDefaultContentProtocol.m 3 | // ios-sdk 4 | // 5 | // Created by xpwu on 2016/11/24. 6 | // Copyright © 2016年 xpwu.xpwu. All rights reserved. 7 | // 8 | 9 | #import "STMDefaultContentProtocol.h" 10 | 11 | #import "Log.h" 12 | 13 | /* 14 | * content protocol: 15 | * request --- 16 | * reqid | headers | header-end-flag | data 17 | * reqid: 4 bytes, net order; 18 | * headers: < key-len | key | value-len | value > ... ; [optional] 19 | * key-len: 1 byte, key-len = sizeof(key); 20 | * value-len: 1 byte, value-len = sizeof(value); 21 | * header-end-flag: 1 byte, === 0; [optional] 22 | * data: [optional] 23 | * 24 | * response --- 25 | * reqid | status | data 26 | * reqid: 4 bytes, net order; 27 | * status: 1 byte, 0---success, 1---failed 28 | * data: if status==success, data= [optional] 29 | * if status==failed, data= 30 | * 31 | */ 32 | 33 | @implementation STMDefaultContentProtocol 34 | 35 | #pragma mark - ContentProtocol 36 | 37 | -(void)onopen:(void (^)(void))callback { 38 | if (callback != nil) { 39 | callback(); 40 | } 41 | } 42 | 43 | -(void)onclose {} 44 | 45 | -(STMResponse*)parse:(NSData*)message { 46 | const uint8_t* p = (const uint8_t*)message.bytes; 47 | 48 | STMResponse* res = [STMResponse defaultResponse]; 49 | res.reqID = ntohl(*(const uint32_t*)p); 50 | p += 4; 51 | 52 | res.status = (STMResponseStatus)*p; 53 | p += 1; 54 | 55 | if (message.length == 5) { 56 | return res; 57 | } 58 | 59 | res.data = [message subdataWithRange:NSMakeRange(5, message.length-5)]; 60 | 61 | return res; 62 | } 63 | 64 | -(NSData*)build:(NSData*)body 65 | withHeaders:(NSDictionary*)headers 66 | withReqID:(uint32_t)reqID { 67 | NSInteger length = 0; 68 | NSInteger* lengthp = &length; 69 | BOOL __block failed = NO; 70 | [headers enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) { 71 | if (key.length > 255 || obj.length > 255) { 72 | *stop = YES; 73 | failed = YES; 74 | } 75 | *lengthp += key.length + obj.length + 1 + 1; 76 | }]; 77 | 78 | if (failed == YES) { 79 | return nil; 80 | } 81 | 82 | length += 4 + 1 + ((body == nil)? 0: body.length); 83 | 84 | char* buffer = calloc(length, sizeof(char)); 85 | char* __block p = buffer; 86 | *(uint32_t*)p = htonl(reqID); 87 | p += 4; 88 | 89 | [headers enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key 90 | , NSString * _Nonnull obj 91 | , BOOL * _Nonnull stop) { 92 | *p = (char)key.length; 93 | p += 1; 94 | if (NO == [key getCString:p maxLength:(length-(p-buffer)) encoding:NSASCIIStringEncoding]) { 95 | failed = YES; 96 | *stop = YES; 97 | return; 98 | } 99 | p += key.length; 100 | 101 | *p = (char)obj.length; 102 | p += 1; 103 | if (NO == [obj getCString:p maxLength:(length-(p-buffer)) encoding:NSASCIIStringEncoding]) { 104 | failed = YES; 105 | *stop = YES; 106 | return; 107 | } 108 | p += obj.length; 109 | }]; 110 | 111 | if (failed == YES) { 112 | return nil; 113 | } 114 | 115 | *p = 0; 116 | p += 1; 117 | 118 | if (body != nil) { 119 | [body getBytes:p length:body.length]; 120 | } 121 | 122 | return [NSData dataWithBytesNoCopy:buffer length:length]; 123 | } 124 | 125 | -(NSData*)buildFailedMessage:(NSString*)error withReqid:(uint32_t)reqID { 126 | NSData* err = [error dataUsingEncoding:NSUTF8StringEncoding]; 127 | char* buffer = calloc(err.length + 4 + 1, sizeof(char)); 128 | [err getBytes:buffer+5 length:err.length]; 129 | buffer[4] = 1; 130 | *(uint32_t*)buffer = htonl(reqID); 131 | 132 | return [NSData dataWithBytesNoCopy:buffer length:err.length + 4 + 1]; 133 | } 134 | @end 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /client/ios/STMNet.h: -------------------------------------------------------------------------------- 1 | // 2 | // STMNet.h 3 | // ios-sdk 4 | // 5 | // Created by xpwu on 2016/11/23. 6 | // Copyright © 2016年 xpwu.xpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum{ 12 | STMNetStatusConnecting, 13 | STMNetStatusOpen, 14 | STMNetStatusClosed 15 | 16 | } STMNetStatus; 17 | 18 | @interface STMNet : NSObject 19 | 20 | @property(nonatomic) void (^onopen)(); 21 | @property(nonatomic) void (^onclose)(NSString*); 22 | @property(nonatomic) void (^onmessage)(NSData*); 23 | @property(nonatomic,readonly) STMNetStatus status; 24 | 25 | // unit: s 26 | @property(nonatomic) NSTimeInterval hearbeatTime; 27 | @property(nonatomic) NSTimeInterval transmissionTimeout; 28 | @property(nonatomic) NSTimeInterval openTimeout; 29 | 30 | -(instancetype)initWithHost:(NSString*)host andPort:(UInt16)port; 31 | 32 | -(void)open; 33 | -(void)close; 34 | -(void)send:(NSData*)data; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /client/ios/STMResponse.h: -------------------------------------------------------------------------------- 1 | // 2 | // STMResponse.h 3 | // ios-sdk 4 | // 5 | // Created by xpwu on 2016/11/24. 6 | // Copyright © 2016年 xpwu.xpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum { 12 | STMResponseStatusSuccess = 0, 13 | STMResponseStatusFailed = 1 14 | } STMResponseStatus; 15 | 16 | @interface STMResponse : NSObject 17 | @property(nonatomic) uint32_t reqID; 18 | @property(nonatomic) STMResponseStatus status; 19 | @property(nonatomic) NSData* data; 20 | 21 | +(instancetype)defaultResponse; 22 | @end 23 | -------------------------------------------------------------------------------- /client/ios/STMResponse.m: -------------------------------------------------------------------------------- 1 | // 2 | // STMResponse.m 3 | // ios-sdk 4 | // 5 | // Created by xpwu on 2016/11/24. 6 | // Copyright © 2016年 xpwu.xpwu. All rights reserved. 7 | // 8 | 9 | #import "STMResponse.h" 10 | 11 | #import "Log.h" 12 | 13 | @implementation STMResponse 14 | +(instancetype)defaultResponse { 15 | STMResponse* res = [[STMResponse alloc]init]; 16 | res.reqID = 0; 17 | res.status = STMResponseStatusSuccess; 18 | res.data = nil; 19 | return res; 20 | } 21 | @end 22 | -------------------------------------------------------------------------------- /client/ios/compile/Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS=-I m4 2 | ##AUTOMAKE_OPTIONS = subdir-objects 3 | AUTOMAKE_OPTIONS = --warnings=none 4 | 5 | noinst_LIBRARIES = libclient_armv7s.a libclient_armv7.a libclient_arm64.a \ 6 | libclient_i386.a libclient_x64.a 7 | #noinst_PROGRAMS = stmclient 8 | 9 | 10 | INCLUDES = -I ${top_srcdir}/.. 11 | 12 | MODE=release 13 | MODE_FLAGS=-DNDEBUG 14 | CXXFLAGS=-O2 15 | CFLAGS=-O2 16 | 17 | # ##---ios var 18 | IOS_MIN_SDK=7.0 19 | ##IPHONEOS_SYSROOT="" 20 | ##IPHONESIMULATOR_SYSROOT="" 21 | if MACOS 22 | XCODEDIR=/Applications/Xcode.app/Contents/Developer 23 | IPHONEOS_SYSROOT=${XCODEDIR}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk 24 | IPHONESIMULATOR_SYSROOT=${XCODEDIR}/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk 25 | else 26 | endif 27 | 28 | COM_CFLAGS=$(MODE_FLAGS) -pipe -fPIC -fobjc-arc -miphoneos-version-min=$(IOS_MIN_SDK)# -fcxx-exceptions 29 | IOS_CFLAGS=-isysroot $(IPHONEOS_SYSROOT) $(COM_CFLAGS) -fembed-bitcode 30 | SIM_CFLAGS=-isysroot ${IPHONESIMULATOR_SYSROOT} $(COM_CFLAGS) 31 | IOS_OBJCFLAGS=${IOS_CFLAGS} 32 | SIM_OBJCFLAGS=${SIM_CFLAGS} 33 | COM_CXXFLAGS=-std=c++11 -stdlib=libc++ 34 | IOS_CXXFLAGS=${IOS_CFLAGS} $(COM_CXXFLAGS) 35 | SIM_CXXFLAGS=${SIM_CFLAGS} $(COM_CXXFLAGS) 36 | IOS_OBJCXXFLAGS=${IOS_CXXFLAGS} 37 | SIM_OBJCXXFLAGS=${SIM_CXXFLAGS} 38 | 39 | 40 | # ##---ios var end 41 | 42 | 43 | ios_common_SOURCES= ${top_srcdir}/../STMClient.m \ 44 | ${top_srcdir}/../STMDefaultContentProtocol.m \ 45 | ${top_srcdir}/../STMNet.mm \ 46 | ${top_srcdir}/../STMResponse.m 47 | 48 | libclient_armv7s_a_SOURCES = $(ios_common_SOURCES) 49 | libclient_armv7s_a_CXXFLAGS=$(IOS_CXXFLAGS) -arch armv7s 50 | libclient_armv7s_a_OBJCXXFLAGS=$(IOS_OBJCXXFLAGS) -arch armv7s 51 | libclient_armv7s_a_OBJCFLAGS=$(IOS_OBJCFLAGS) -arch armv7s 52 | 53 | libclient_armv7_a_SOURCES = $(ios_common_SOURCES) 54 | libclient_armv7_a_CXXFLAGS=$(IOS_CXXFLAGS) -arch armv7 55 | libclient_armv7_a_OBJCXXFLAGS=$(IOS_OBJCXXFLAGS) -arch armv7 56 | libclient_armv7_a_OBJCFLAGS=$(IOS_OBJCFLAGS) -arch armv7 57 | 58 | libclient_arm64_a_SOURCES = $(ios_common_SOURCES) 59 | libclient_arm64_a_CXXFLAGS=$(IOS_CXXFLAGS) -arch arm64 60 | libclient_arm64_a_OBJCXXFLAGS=$(IOS_OBJCXXFLAGS) -arch arm64 61 | libclient_arm64_a_OBJCFLAGS=$(IOS_OBJCFLAGS) -arch arm64 62 | 63 | libclient_i386_a_SOURCES = $(ios_common_SOURCES) 64 | libclient_i386_a_CXXFLAGS=$(SIM_CXXFLAGS) -arch i386 65 | libclient_i386_a_OBJCXXFLAGS=$(SIM_OBJCXXFLAGS) -arch i386 66 | libclient_i386_a_OBJCFLAGS=$(SIM_OBJCFLAGS) -arch i386 67 | 68 | libclient_x64_a_SOURCES = $(ios_common_SOURCES) 69 | libclient_x64_a_CXXFLAGS=$(SIM_CXXFLAGS) -arch x86_64 70 | libclient_x64_a_OBJCXXFLAGS=$(SIM_OBJCXXFLAGS) -arch x86_64 71 | libclient_x64_a_OBJCFLAGS=$(SIM_OBJCFLAGS) -arch x86_64 72 | 73 | #stmclient_SOURCES = ${top_srcdir}/../ios-sdk/ios-sdk/main.m 74 | #stmclient_OBJCFLAGS = $(MODE_FLAGS) -isysroot ${XCODEDIR}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk 75 | #stmclient_LDFLAGS = -framework Foundation 76 | #stmclient_LDADD = ${top_srcdir}/../out/$(MODE)/libstmclient.a 77 | 78 | all-local:libclient_armv7.a libclient_arm64.a libclient_i386.a libclient_x64.a libclient_armv7s.a # stmclient 79 | @if ! [ -d ${top_srcdir}/../out/$(MODE) ] ;then \ 80 | mkdir -p ${top_srcdir}/../out/$(MODE); \ 81 | fi 82 | lipo -create libclient_armv7.a libclient_arm64.a libclient_i386.a libclient_x64.a libclient_armv7s.a \ 83 | -output ${top_srcdir}/../out/$(MODE)/libstmclient.a 84 | @cp ${top_srcdir}/../STMClient.h ${top_srcdir}/../out/STMClient.h 85 | # @cp stmclient ${top_srcdir}/../out/$(MODE)/stmclient 86 | @echo "BUILD SUCCESS ---out/$(MODE)" 87 | 88 | 89 | debug: 90 | $(MAKE) all CFLAGS="-g" CXXFLAGS="-g" MODE="debug" MODE_FLAGS="-DDEBUG" 91 | 92 | 93 | -------------------------------------------------------------------------------- /client/ios/compile/autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | touch NEWS README AUTHORS ChangeLog 4 | 5 | aclocal && autoconf && automake -a 6 | -------------------------------------------------------------------------------- /client/ios/compile/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.69]) 5 | AC_INIT([stmclient], [VERSION], [BUG-REPORT-ADDRESS]) 6 | AM_INIT_AUTOMAKE 7 | # AC_CONFIG_SRCDIR([STMClient.h]) 8 | # AC_CONFIG_HEADERS([config.h]) 9 | 10 | AM_CONDITIONAL([MACOS], [test "x$(uname -s)" = "xDarwin"]) 11 | 12 | # Checks for programs. 13 | AC_PROG_CXX 14 | AC_PROG_CC 15 | AC_PROG_CPP 16 | AC_PROG_RANLIB 17 | AC_PROG_OBJCXX 18 | AM_PROG_CC_C_O 19 | AC_PROG_OBJC 20 | # Checks for libraries. 21 | 22 | # Checks for header files. 23 | 24 | # Checks for typedefs, structures, and compiler characteristics. 25 | AC_TYPE_UINT16_T 26 | AC_TYPE_UINT32_T 27 | AC_TYPE_UINT8_T 28 | 29 | # Checks for library functions. 30 | 31 | AC_OUTPUT([Makefile]) 32 | -------------------------------------------------------------------------------- /client/ios/ios-sdk/ios-sdk/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ios-sdk 4 | // 5 | // Created by xpwu on 2016/11/23. 6 | // Copyright © 2016年 xpwuxpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "STMClient.h" 12 | 13 | @interface RunLoopSource : NSObject 14 | -(void)perform:(id)message; 15 | @end 16 | 17 | @implementation RunLoopSource 18 | -(void)perform:(id)message { 19 | void (^msg)(void) = message; 20 | msg(); 21 | } 22 | @end 23 | 24 | #define RUNLOOP_INIT \ 25 | RunLoopSource* src = [[RunLoopSource alloc]init]; \ 26 | [[NSRunLoop mainRunLoop]performSelector:@selector(perform:) \ 27 | target:src argument:^(void) { 28 | 29 | 30 | #define RUNLOOP_RUN \ 31 | } \ 32 | order:0 modes:@[NSDefaultRunLoopMode]]; \ 33 | \ 34 | [[NSRunLoop mainRunLoop]run]; 35 | 36 | 37 | int main(int argc, const char * argv[]) { 38 | @autoreleasepool { 39 | 40 | RUNLOOP_INIT 41 | 42 | STMClient* client = [[STMClient alloc]init]; 43 | 44 | STMClient* __weak client_ = client; 45 | [client setConnectHost:@"ssl://www.xpwu.me" port:10005 46 | onSuccess:^{ 47 | NSLog(@"connect successful"); 48 | } 49 | onFailed:^(NSString * error) { 50 | NSLog(@"connect failed: %@", error); 51 | [client_ addRequestBody:[@"add message" dataUsingEncoding:NSUTF8StringEncoding] 52 | headers:@{@"h":@"test", @"ua": @"request ua"} 53 | onSuccess:^(NSData * data) { 54 | NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 55 | } 56 | onFailed:^(NSString * error) { 57 | NSLog(@"%@", error); 58 | } 59 | onComplete:^{ 60 | NSLog(@"request complete"); 61 | }]; 62 | }]; 63 | 64 | client.onpush = ^(NSData* data) { 65 | NSLog(@"[push]---%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 66 | }; 67 | 68 | [client setBlockRequestOnConnected:[@"block message" dataUsingEncoding:NSUTF8StringEncoding] 69 | headers:@{@"name": @"block message"} 70 | onSuccess:^BOOL(NSData * data) { 71 | NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 72 | return YES; 73 | } 74 | onFailed:^(NSString * error) { 75 | NSLog(@"%@", error); 76 | } 77 | onComplete:^{ 78 | NSLog(@"block message complete"); 79 | }]; 80 | 81 | [client addRequestBody:[@"add message" dataUsingEncoding:NSUTF8StringEncoding] 82 | headers:@{@"h":@"test", @"ua": @"request ua"} 83 | onSuccess:^(NSData * data) { 84 | NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 85 | } 86 | onFailed:^(NSString * error) { 87 | NSLog(@"%@", error); 88 | } 89 | onComplete:^{ 90 | NSLog(@"request complete"); 91 | }]; 92 | 93 | [client addRequestBody:nil 94 | headers:@{@"h":@"test", @"ua": @"request ua 2"} 95 | onSuccess:^(NSData * data) { 96 | NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 97 | } 98 | onFailed:^(NSString * error) { 99 | NSLog(@"%@", error); 100 | } 101 | onComplete:^{ 102 | NSLog(@"request complete"); 103 | }]; 104 | 105 | [client addRequestBody:nil 106 | headers:nil 107 | onSuccess:^(NSData * data) { 108 | NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 109 | } 110 | onFailed:^(NSString * error) { 111 | NSLog(@"%@", error); 112 | } 113 | onComplete:^{ 114 | NSLog(@"request complete"); 115 | }]; 116 | 117 | [client addRequestBody:nil 118 | headers:@{@"h":@"test", @"ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);ua NSLog(, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);": @"request ua 2"} 119 | onSuccess:^(NSData * data) { 120 | NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 121 | } 122 | onFailed:^(NSString * error) { 123 | NSLog(@"%@", error); 124 | } 125 | onComplete:^{ 126 | NSLog(@"request complete"); 127 | }]; 128 | 129 | RUNLOOP_RUN 130 | 131 | } 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /client/ios/out/STMClient.h: -------------------------------------------------------------------------------- 1 | // 2 | // STMClient.h 3 | // ios-sdk 4 | // 5 | // Created by xpwu on 2016/11/24. 6 | // Copyright © 2016年 xpwu.xpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface STMClient : NSObject 12 | 13 | @property(nonatomic) void (^onpush)(NSData*); 14 | 15 | // unit: s 16 | // default 30s; 4*60s; 10s 17 | -(void)setConfigConnectionTimeout:(NSTimeInterval)ctime_s 18 | heartbeat:(NSTimeInterval)htime_s 19 | transmission:(NSTimeInterval)ttime_s; 20 | 21 | 22 | -(void)setConnectHost:(NSString*)host 23 | port:(uint16_t)port; 24 | 25 | -(void)setConnectHost:(NSString*)host 26 | port:(uint16_t)port 27 | onSuccess:(void (^)(void))suc; 28 | 29 | -(void)setConnectHost:(NSString*)host 30 | port:(uint16_t)port 31 | onSuccess:(void (^)(void))suc 32 | onFailed:(void (^)(NSString*))failed; 33 | 34 | 35 | /** 36 | All args can be set nil; 37 | onSuccess: only callback for successful. 38 | onFailed: only callback for failed 39 | complete: callback wether successful or failed 40 | */ 41 | 42 | -(void)addRequestBody:(NSData*)body 43 | onSuccess:(void (^)(NSData*))suc; 44 | 45 | -(void)addRequestBody:(NSData*)body 46 | headers:(NSDictionary*)headers 47 | onSuccess:(void (^)(NSData*))suc; 48 | 49 | -(void)addRequestBody:(NSData*)body 50 | headers:(NSDictionary*)headers 51 | onSuccess:(void (^)(NSData*))suc 52 | onFailed:(void (^)(NSString*))failed; 53 | 54 | -(void)addRequestBody:(NSData*)body 55 | headers:(NSDictionary*)headers 56 | onSuccess:(void (^)(NSData*))suc 57 | onFailed:(void (^)(NSString*))failed 58 | onComplete:(void (^)())complete; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /client/ios/out/release/libstmclient.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xpwu/ngx-stream-request-module/a1d1d46e31844142c22e12e76606e9fb13540eac/client/ios/out/release/libstmclient.a -------------------------------------------------------------------------------- /client/ios/test-stm/test-stm.xcodeproj/xcuserdata/xpwu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | test-stm.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | A425F1251DFFAA7000854907 16 | 17 | primary 18 | 19 | 20 | A425F13E1DFFAA7000854907 21 | 22 | primary 23 | 24 | 25 | A425F1491DFFAA7000854907 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stm/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // test-stm 4 | // 5 | // Created by xpwu on 2016/12/13. 6 | // Copyright © 2016年 xpwuxpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stm/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // test-stm 4 | // 5 | // Created by xpwu on 2016/12/13. 6 | // Copyright © 2016年 xpwuxpwu. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stm/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /client/ios/test-stm/test-stm/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stm/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stm/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stm/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // test-stm 4 | // 5 | // Created by xpwu on 2016/12/13. 6 | // Copyright © 2016年 xpwuxpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | -(IBAction)selector:(id)sender; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stm/ViewController.mm: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // test-stm 4 | // 5 | // Created by xpwu on 2016/12/13. 6 | // Copyright © 2016年 xpwuxpwu. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | //#import "../../out/STMClient.h" 11 | #import "../../STMClient.h" 12 | 13 | @interface ViewController () { 14 | STMClient* client; 15 | STMClient* client2; 16 | } 17 | 18 | @end 19 | 20 | @implementation ViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view, typically from a nib. 25 | client = [[STMClient alloc]init]; 26 | client2 = [[STMClient alloc]init]; 27 | 28 | [client setConnectHost:@"127.0.0.1" port:8000 29 | onSuccess:^{ 30 | NSLog(@"client1 connect successful"); 31 | } 32 | onFailed:^(NSString * error) { 33 | NSLog(@"client1 %@", error); 34 | }]; 35 | [client2 setConnectHost:@"127.0.0.1" port:8002 36 | onSuccess:^{ 37 | NSLog(@"client2 connect successful"); 38 | } 39 | onFailed:^(NSString * error) { 40 | NSLog(@"client2 %@", error); 41 | }]; 42 | 43 | client.onpush = ^(NSData* data) { 44 | NSLog(@"[client1 push]---%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 45 | }; 46 | 47 | client2.onpush = ^(NSData* data) { 48 | NSLog(@"[client2 push]---%@" 49 | , [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 50 | }; 51 | 52 | [client addRequestBody:[@"flajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflaflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklf" dataUsingEncoding:NSUTF8StringEncoding] headers:@{@"api": @"/api/ServerInfo"} onSuccess:^(NSData * data) { 53 | NSLog(@"client1 success, %@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 54 | } onFailed:^(NSString * str) { 55 | NSLog(@"client1 %@", str); 56 | } onComplete:^{ 57 | NSLog(@"client1 complete"); 58 | }]; 59 | 60 | [client addRequestBody:[@"flajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflaflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklf" dataUsingEncoding:NSUTF8StringEncoding] headers:@{@"api": @"/api/php/info"} onSuccess:^(NSData * data) { 61 | NSLog(@"client1 success, %@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 62 | } onFailed:^(NSString * str) { 63 | NSLog(@"client1 %@", str); 64 | } onComplete:^{ 65 | NSLog(@"client1 complete"); 66 | }]; 67 | 68 | [client2 addRequestBody:[@"client2" dataUsingEncoding:NSUTF8StringEncoding] headers:@{@"api": @"api/php/info"} onSuccess:^(NSData * data) { 69 | NSLog(@"client2 success, %@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 70 | } onFailed:^(NSString * str) { 71 | NSLog(@"client2 %@", str); 72 | } onComplete:^{ 73 | NSLog(@"client2 complete"); 74 | }]; 75 | } 76 | 77 | - (void)didReceiveMemoryWarning { 78 | [super didReceiveMemoryWarning]; 79 | // Dispose of any resources that can be recreated. 80 | } 81 | 82 | -(IBAction)selector:(id)sender { 83 | [client addRequestBody:[@"flajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflaflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklfjsdklflajsfjklsdfjklasdklf" dataUsingEncoding:NSUTF8StringEncoding] headers:@{@"api": @"/api/php/info"} onSuccess:^(NSData * data) { 84 | NSLog(@"client1 success, %@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 85 | } onFailed:^(NSString * str) { 86 | NSLog(@"client1 %@", str); 87 | } onComplete:^{ 88 | NSLog(@"client1 complete"); 89 | }]; 90 | 91 | 92 | [client2 addRequestBody:[@"client2" dataUsingEncoding:NSUTF8StringEncoding] headers:@{@"api": @"api/php/info"} onSuccess:^(NSData * data) { 93 | NSLog(@"client2 success, %@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 94 | } onFailed:^(NSString * str) { 95 | NSLog(@"client2 %@", str); 96 | } onComplete:^{ 97 | NSLog(@"client2 complete"); 98 | }]; 99 | 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stm/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // test-stm 4 | // 5 | // Created by xpwu on 2016/12/13. 6 | // Copyright © 2016年 xpwuxpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stmTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stmTests/test_stmTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // test_stmTests.m 3 | // test-stmTests 4 | // 5 | // Created by xpwu on 2016/12/13. 6 | // Copyright © 2016年 xpwuxpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface test_stmTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation test_stmTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stmUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /client/ios/test-stm/test-stmUITests/test_stmUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // test_stmUITests.m 3 | // test-stmUITests 4 | // 5 | // Created by xpwu on 2016/12/13. 6 | // Copyright © 2016年 xpwuxpwu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface test_stmUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation test_stmUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /client/java/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /client/java/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /client/java/out/artifacts/stm_client/stm.client.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xpwu/ngx-stream-request-module/a1d1d46e31844142c22e12e76606e9fb13540eac/client/java/out/artifacts/stm_client/stm.client.jar -------------------------------------------------------------------------------- /client/java/src/stm/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /client/java/src/stm/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /client/java/src/stm/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /client/java/src/stm/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /client/java/src/stm/Client.java: -------------------------------------------------------------------------------- 1 | package stm; 2 | 3 | import java.security.cert.X509Certificate; 4 | import java.util.ArrayList; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * 10 | * Created by xpwu on 2016/11/28. 11 | */ 12 | 13 | public class Client{ 14 | public interface Delegate { 15 | public void onPush(byte[] data); 16 | } 17 | 18 | public void pump() { 19 | if (net_ == null) { 20 | return; 21 | } 22 | net_.pump(); 23 | } 24 | public interface AsyncEventHandler extends Net.AsyncEventHandler{} 25 | public void setAsyncEventHandler(AsyncEventHandler handler) { 26 | handler_ = handler; 27 | if (net_ != null) { 28 | net_.setAsyncEventHandler(handler_); 29 | } 30 | } 31 | 32 | public interface NetCallback { 33 | public void onSuccess(); 34 | public void onFailed(String error); 35 | } 36 | public void setConnectHostAndPort(String host, int port, NetCallback callback){ 37 | net_ = new Net(host, port); 38 | net_.setDelegate(new Net.Delegate() { 39 | public void onOpen(){ 40 | Client.this.sendAllRequests(); 41 | Client.this.netCallback_.onSuccess(); 42 | } 43 | 44 | public void onClose(String reason){ 45 | Client.this.errorAllRequests(reason); 46 | Client.this.netCallback_.onFailed(reason); 47 | } 48 | 49 | public void onMessage(byte[] data){ 50 | Client.this.messageHandler_.handle(data); 51 | } 52 | }); 53 | this.netCallback_ = callback; 54 | net_.setAsyncEventHandler(handler_); 55 | net_.setConfig(config_); 56 | net_.setTrustX509Certificate(ca_); 57 | } 58 | 59 | // unit: s default: 30s; 4*60s; 10s 60 | public void setConfig(int connectTimeout, int heartbeatTime, int transmission) { 61 | config_.connectTimeout_ms = connectTimeout * 1000; 62 | config_.hearbeatTime_ms = heartbeatTime * 1000; 63 | config_.translatioin_ms = transmission * 1000; 64 | if (net_ != null) { 65 | net_.setConfig(config_); 66 | } 67 | } 68 | 69 | public void setTrustX509Certificate(X509Certificate ca) { 70 | ca_ = ca; 71 | if (net_ != null) { 72 | net_.setTrustX509Certificate(ca_); 73 | } 74 | } 75 | 76 | public interface RequestCallback { 77 | public void onSuccess(byte[] data); 78 | public void onFailed(String error); 79 | public void onComplete(); 80 | } 81 | public void addRequest(byte[] body 82 | , Mapheaders 83 | , RequestCallback callback){ 84 | if (net_ == null) { 85 | callback.onComplete(); 86 | callback.onFailed("host and port not set!"); 87 | return; 88 | } 89 | if (handler_ == null) { 90 | callback.onComplete(); 91 | callback.onFailed("async Event Handler not set!"); 92 | return; 93 | } 94 | 95 | long id = reqID(); 96 | Request request = new Request(); 97 | request.body = body; 98 | request.headers = headers; 99 | request.requestCallback = callback; 100 | request.reqID = id; 101 | 102 | requests_.put(id, request); 103 | 104 | if (net_.status() == Net.Status.Open) { 105 | sendRequest(body, headers, id); 106 | return; 107 | } 108 | if (net_.status() == Net.Status.Connecting) { 109 | return; 110 | } 111 | connect(); 112 | } 113 | 114 | public Client() { 115 | reqID_ = reqIDstart; 116 | net_ = null; 117 | protocol_ = new DefaultContentProtocol(); 118 | requests_ = new HashMap(); 119 | ca_ = null; 120 | delegate_ = new Delegate() { 121 | @Override 122 | public void onPush(byte[] data) { 123 | // TODO debug log 124 | } 125 | }; 126 | config_ = new Net.Config(); 127 | config_.hearbeatTime_ms = 4*60*1000; 128 | config_.translatioin_ms = 10*1000; 129 | config_.connectTimeout_ms = 30*1000; 130 | } 131 | 132 | public void setDelegate(Delegate delegate) { 133 | this.delegate_ = delegate; 134 | } 135 | 136 | // ---- private class ---- 137 | private class Request { 138 | long reqID; 139 | byte[] body; 140 | Map headers; 141 | RequestCallback requestCallback; 142 | } 143 | 144 | private interface MessageHandler { 145 | public void handle(byte[] message); 146 | } 147 | 148 | private long reqID(){ 149 | reqID_++; 150 | if (reqID_ < reqIDstart || reqID_ > Integer.MAX_VALUE) { 151 | reqID_ = reqIDstart; 152 | } 153 | return reqID_; 154 | } 155 | 156 | private void connect(){ 157 | normalMessageHandler_ = new MessageHandler() { 158 | @Override 159 | public void handle(byte[] message) { 160 | Response response = protocol_.parse(message); 161 | 162 | if (response.reqID == pushID) { 163 | Client.this.delegate_.onPush(response.data); 164 | return; 165 | } 166 | 167 | Request request = Client.this.requests_.get(response.reqID); 168 | if (request == null) { 169 | // System.out.println("not find request"); 170 | return; 171 | } 172 | request.requestCallback.onComplete(); 173 | if (response.status != Response.Status.Success) { 174 | if (response.data == null) { 175 | request.requestCallback.onFailed("may be server error, but server has closed the error log"); 176 | } else { 177 | try { 178 | request.requestCallback.onFailed(new String(response.data, "UTF-8")); 179 | } catch (java.io.UnsupportedEncodingException e) { 180 | request.requestCallback.onFailed("unkown error, because java utf-8 error"); 181 | } 182 | } 183 | } else { 184 | request.requestCallback.onSuccess(response.data); 185 | } 186 | 187 | Client.this.requests_.remove(response.reqID); 188 | } 189 | }; 190 | this.messageHandler_ = normalMessageHandler_; 191 | 192 | net_.open(); 193 | } 194 | 195 | private void sendAllRequests(){ 196 | for (Request request : requests_.values()) { 197 | sendRequest(request.body, request.headers, request.reqID); 198 | } 199 | } 200 | 201 | private void sendRequest(byte[] body, Mapheaders, final long reqID){ 202 | byte[] data = protocol_.build(body, headers, reqID); 203 | if (data == null) { 204 | net_.postTask(new Net.Task() { 205 | public void run() { 206 | Client.this.messageHandler_.handle(Client.this.protocol_.buildFailedMessage("build message error, maybe length of headers' key or value > 255, or is not asscii", reqID)); 207 | } 208 | }); 209 | return; 210 | } 211 | 212 | net_.send(data); 213 | } 214 | 215 | private void errorAllRequests(String error){ // async call 216 | ArrayList requests = new ArrayList<>(requests_.size()); 217 | requests.addAll(requests_.values()); 218 | for (Request request : requests) { 219 | normalMessageHandler_.handle(protocol_.buildFailedMessage(error, request.reqID)); 220 | } 221 | try { 222 | requests_.clear(); 223 | } catch (UnsupportedOperationException e) { 224 | requests_ = new HashMap(); 225 | } 226 | } 227 | 228 | private Net net_; 229 | private NetCallback netCallback_; 230 | private ContentProtocol protocol_; 231 | private Map requests_; 232 | private long reqID_; 233 | private MessageHandler messageHandler_; 234 | private MessageHandler normalMessageHandler_; 235 | private Delegate delegate_; 236 | private AsyncEventHandler handler_; 237 | private Net.Config config_; 238 | private X509Certificate ca_; 239 | 240 | private static final long reqIDstart = 200; 241 | private static final long pushID = 1; // need equal server 242 | } 243 | -------------------------------------------------------------------------------- /client/java/src/stm/ContentProtocol.java: -------------------------------------------------------------------------------- 1 | package stm; 2 | 3 | /** 4 | * 5 | * Created by xpwu on 2016/11/29. 6 | */ 7 | 8 | import java.util.Map; 9 | 10 | interface ContentProtocol { 11 | public Response parse(byte[] content); 12 | public byte[] build(byte[] body, Mapheaders, long reqID); 13 | public byte[] buildFailedMessage(String error, long reqID); 14 | } 15 | -------------------------------------------------------------------------------- /client/java/src/stm/DefaultContentProtocol.java: -------------------------------------------------------------------------------- 1 | package stm; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.util.Arrays; 5 | import java.util.Map; 6 | 7 | /** 8 | * 9 | * Created by xpwu on 2016/11/29. 10 | */ 11 | 12 | /** 13 | * content protocol: 14 | * request --- 15 | * reqid | headers | header-end-flag | data 16 | * reqid: 4 bytes, net order; 17 | * headers: < key-len | key | value-len | value > ... ; [optional] 18 | * key-len: 1 byte, key-len = sizeof(key); 19 | * value-len: 1 byte, value-len = sizeof(value); 20 | * header-end-flag: 1 byte, === 0; [optional] 21 | * data: [optional] 22 | * 23 | * response --- 24 | * reqid | status | data 25 | * reqid: 4 bytes, net order; 26 | * status: 1 byte, 0---success, 1---failed 27 | * data: if status==success, data= [optional] 28 | * if status==failed, data= 29 | * 30 | */ 31 | 32 | class DefaultContentProtocol implements ContentProtocol { 33 | public Response parse(byte[] content){ 34 | Response res = new Response(); 35 | res.reqID = 0; 36 | for (int i = 0; i < 4; ++i) { 37 | res.reqID = (res.reqID << 8) + (content[i]&0xff); 38 | } 39 | res.status = content[4] == 0? Response.Status.Success : Response.Status.Failed; 40 | if (content.length <= 5) { 41 | return res; 42 | } 43 | try { 44 | res.data = Arrays.copyOfRange(content, 5, content.length); 45 | } catch (Exception e) { 46 | res.data = null; 47 | } 48 | return res; 49 | } 50 | 51 | public byte[] build(byte[] body, Map headers, long reqID){ 52 | int length = 4 + 1; 53 | if (body != null) { 54 | length += body.length; 55 | } 56 | if (headers != null) { 57 | for (Map.Entry entry : headers.entrySet()) { 58 | byte[] key = null; 59 | byte[] value = null; 60 | try { 61 | key = entry.getKey().getBytes("UTF-8"); 62 | value = entry.getValue().getBytes("UTF-8"); 63 | } catch (UnsupportedEncodingException e) { 64 | return null; 65 | } 66 | if (key.length > 255 || value.length > 255) { 67 | return null; 68 | } 69 | length += 1 + key.length + 1 + value.length; 70 | } 71 | } 72 | 73 | byte[] request = new byte[length]; 74 | request[0] = (byte) ((reqID & 0xff000000) >> 24); 75 | request[1] = (byte) ((reqID & 0xff0000) >> 16); 76 | request[2] = (byte) ((reqID & 0xff00) >> 8); 77 | request[3] = (byte) (reqID & 0xff); 78 | 79 | int pos = 4; 80 | if (headers != null) { 81 | for (Map.Entry entry : headers.entrySet()) { 82 | byte[] key = null; 83 | byte[] value = null; 84 | try { 85 | key = entry.getKey().getBytes("UTF-8"); 86 | value = entry.getValue().getBytes("UTF-8"); 87 | } catch (UnsupportedEncodingException e) { 88 | return null; 89 | } 90 | if (key.length > 255 || value.length > 255) { 91 | return null; 92 | } 93 | request[pos] = (byte) key.length; 94 | pos++; 95 | System.arraycopy(key, 0, request, pos, key.length); 96 | pos += key.length; 97 | request[pos] = (byte) value.length; 98 | pos++; 99 | System.arraycopy(value, 0, request, pos, value.length); 100 | pos += value.length; 101 | } 102 | } 103 | request[pos] = 0; // header-end 104 | pos++; 105 | 106 | if (body != null) { 107 | System.arraycopy(body, 0, request, pos, body.length); 108 | } 109 | 110 | return request; 111 | } 112 | 113 | public byte[] buildFailedMessage(String error, long reqID){ 114 | byte[] msg = null; 115 | try { 116 | byte[] err = error.getBytes("UTF-8"); 117 | msg = new byte[err.length + 1 + 4]; 118 | System.arraycopy(err, 0, msg, 5, err.length); 119 | }catch (UnsupportedEncodingException e) { 120 | msg = new byte[4 + 1]; 121 | } 122 | msg[0] = (byte) ((reqID & 0xff000000) >> 24); 123 | msg[1] = (byte) ((reqID & 0xff0000) >> 16); 124 | msg[2] = (byte) ((reqID & 0xff00) >> 8); 125 | msg[3] = (byte) (reqID & 0xff); 126 | msg[4] = 1; 127 | 128 | return msg; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /client/java/src/stm/Response.java: -------------------------------------------------------------------------------- 1 | package stm; 2 | 3 | import org.omg.CORBA.PUBLIC_MEMBER; 4 | 5 | /** 6 | * 7 | * Created by xpwu on 2016/11/29. 8 | */ 9 | class Response { 10 | enum Status { 11 | Success(0), Failed(1); 12 | 13 | private int code_ = 0; 14 | private Status(int code) { 15 | this.code_ = code; 16 | } 17 | } 18 | 19 | long reqID; 20 | byte[] data; 21 | Status status; 22 | 23 | static public Response defaultResponse(){ 24 | Response res = new Response(); 25 | res.reqID = 0; 26 | res.status = Status.Success; 27 | res.data = null; 28 | 29 | return res; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /client/java/test/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: Main 3 | Class-Path: ../stm_client/stm.client.jar 4 | 5 | 6 | -------------------------------------------------------------------------------- /client/java/test/MainThreadLooper.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.LinkedList; 3 | import java.util.List; 4 | 5 | /** 6 | * 7 | * Created by xpwu on 2016/11/30. 8 | */ 9 | 10 | public class MainThreadLooper { 11 | static interface Handler { 12 | public void run(); 13 | } 14 | 15 | static private final List queue = new LinkedList<>(); 16 | 17 | static void addHandler(Handler handler) { 18 | synchronized (queue) { 19 | queue.add(handler); 20 | queue.notify(); 21 | } 22 | } 23 | 24 | static void loop() { 25 | while (true) { 26 | synchronized (queue) { 27 | while (queue.isEmpty()) { 28 | try { 29 | queue.wait(); 30 | } catch (InterruptedException e) {} 31 | } 32 | ArrayList handlers = new ArrayList<>(queue.size()); 33 | handlers.addAll(queue); 34 | for (Handler task: handlers) { 35 | task.run(); 36 | queue.remove(task); 37 | } 38 | // task.run() 执行过程中, 可能会产生新的task 39 | // queue.clear(); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /client/js/.idea/js.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /client/js/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /client/js/dest/stm.client.extern.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xpwu on 2016/11/22. 3 | */ 4 | 5 | /* 6 | this file only for IDE 7 | */ 8 | 9 | console.error("this file only for IDE"); 10 | 11 | stm = stm || {}; 12 | 13 | stm.Client = function () { 14 | /** 15 | * @callback pushCallback 16 | * @param {ArrayBuffer} 17 | */ 18 | 19 | /** 20 | * 21 | * @type pushCallback 22 | */ 23 | this.onPush = 0; 24 | 25 | /** 26 | * 27 | * @var {function(Object)} 28 | */ 29 | this.onPushJson = null; 30 | }; 31 | 32 | /** 33 | * 34 | * @param {number} connectTimeout unit: s 35 | */ 36 | stm.Client.prototype.setConfig = function (connectTimeout){}; 37 | 38 | /** 39 | * 40 | * @param {string}url, ws(s)://xxx.xxx.xx:xxx/xxxx 41 | * @param {function()|null} [onSuccess] 42 | * @param {function(string)|null} [onFailed] 43 | */ 44 | stm.Client.prototype.setConnectArgs = function(url, onSuccess, onFailed){}; 45 | 46 | /** 47 | * 48 | * @param {Object|null} [body] 49 | * @param {function(Object)|null} [onSuccess] 50 | * S 51 | * @param {Object|null} [headers] 52 | * @param {function(string)|null} [onFailed] 53 | * @param {function()|null} [onComplete] 54 | */ 55 | stm.Client.prototype.addJsonRequest = function (body, onSuccess, headers, onFailed, onComplete) {}; 56 | 57 | /** 58 | * 59 | * @param {ArrayBuffer|string|null} [body] 60 | * @param {function(ArrayBuffer)|null} [onSuccess] 61 | * @param {Object|null} [headers] 62 | * @param {function(string)|null} [onFailed] 63 | * @param {function()|null} [onComplete] 64 | */ 65 | stm.Client.prototype.addRequest = function (body, onSuccess, headers, onFailed, onComplete) {}; 66 | -------------------------------------------------------------------------------- /client/js/dest/stm.client.min.js: -------------------------------------------------------------------------------- 1 | !function(t){"use strict";function e(){this.reqID=0,this.state=r.Success,this.data=null}var n=t.stm=t.stm||{},r={Success:0,Failed:1};n.Response=e,n.Response.State=r}(this),function(t){"use strict";var e=t.stm=t.stm||{};e.ContentProtocol={onOpen:function(t){t()},onClose:function(){},parse:function(t){return new e.Response},build:function(t,e,n){return new ArrayBuffer(2)},buildFailedMessage:function(t,e){return new ArrayBuffer(2)},extend:function(t){if(t.__proto__)t.__proto__=this;else{for(var e in this)this.hasOwnProperty(e)&&!t.hasOwnProperty(e)&&(t[e]=this[e]);this.hasOwnProperty("toString")&&!t.hasOwnProperty("toString")&&(t.toString=this.toString)}return t.$parent=this,t}}}(this),function(t){"use strict";var e=t.stm=t.stm||{};e.DefaultContentProtocol={parse:function(t){var n=new e.Response,r=new DataView(t);return n.reqID=r.getUint32(0),n.state=0==r.getUint8(4)?e.Response.State.Success:e.Response.State.Failed,n.data=t.slice(5),n},build:function(t,e,n){if(t=t||"","string"!=typeof t&&!(t instanceof ArrayBuffer))return"body type is error, must be string or ArrayBuffer";if(e=e||{},"object"!=typeof e)return"headers must be a object type, for example {uri: '/location'}";var r=0;for(var o in e)if(e.hasOwnProperty(o)){if("string"!=typeof o||"string"!=typeof e[o])return"headers' key or property must be string";if(o.length>255)return"length of headers' key <"+o+"> more than 255";if(e[o].length>255)return"length of headers' object <"+e[o]+"> more than 255";0!=o.length&&0!=e[o].length&&(r+=2+o.length+e[o].length)}t=new StringView(t);var i=new ArrayBuffer(4+t.rawData.byteLength+1+r);new DataView(i).setUint32(0,n);var s=4;for(o in e)e.hasOwnProperty(o)&&(new DataView(i).setUint8(s,o.length),s++,new Uint8Array(i).set(new StringView(o).rawData,s),s+=o.length,new DataView(i).setUint8(s,e[o].length),s++,new Uint8Array(i).set(new StringView(e[o]).rawData,s),s+=e[o].length);return new DataView(i).setUint8(s,0),s++,new Uint8Array(i).set(t.rawData,s),i},buildFailedMessage:function(t,n){t=new StringView(t);var r=new ArrayBuffer(4+t.rawData.byteLength+1);return new DataView(r).setUint32(0,n),new DataView(r).setUint8(4,e.Response.State.Failed),new Uint8Array(r).set(t.rawData,5),r}}}(this),function(t){"use strict";function e(t,e,n,r,o,i){this.body=t||"",this.headers=n||{},this.onSuccess=e||function(t){},this.onFailed=r||function(t){},this.onComplete=o||function(){},this.reqID=i}function n(){function t(t){t.net_=null,t.netArgs_="",t.requests_=Object.create(null),t.protocol_=l.ContentProtocol.extend(l.DefaultContentProtocol),t.reqID_=s,t.onConnectionSuc_=function(){},t.onConnectionFaild_=function(t){},t.normalOnMessage_=function(t){},t.connectTimeout_=30}t(this),this.onPush=function(t){},this.onPushJson=null}function r(t){return new i(t)}function o(t){setTimeout(t,0)}function i(t){this.client_=t}if("function"!=typeof StringView)return void console.error("can not find StringView. this error maybe cause 'stm.Client is not a constructor'. you can find in https://developer.mozilla.org/en-US/Add-ons/Code_snippets/StringView or https://github.com/madmurphy/stringview.js");var s=200,a=1,u=n.prototype;u.setConnectArgs=function(t,e,n){this.netArgs_=t,this.onConnectionFaild_=n||function(t){},this.onConnectionSuc_=e||function(){}},u.setConfig=function(t){this.connectTimeout_=t},u.addJsonRequest=function(t,e,n,r,o){var i=null==e?null:function(t){e(JSON.parse(new StringView(t).toString()))};this.addRequest(JSON.stringify(null===t?null:t),i,n,r,o)},u.addRequest=function(t,n,o,i,s){if(null==this.netArgs_)return"function"==typeof s&&s(),void("function"==typeof i&&i("net args not set"));var a=r(this).getReqID();return this.requests_[a.toString()]=new e(t,n,o,i,s,a),null!=this.net_&&this.net_.readyState==WebSocket.OPEN?void r(this).sendRequest(this.requests_[a.toString()]):void(null!=this.net_&&this.net_.readyState==WebSocket.CONNECTING||r(this).connect())};var c=i.prototype;c.getReqID=function(){return this.client_.reqID_++,this.client_.reqID_"):(r.onComplete(),n.state!=l.Response.State.Success?null===n.data||void 0===n.data?r.onFailed("may be server error, but server has closed the error log"):r.onFailed(new StringView(n.data).toString()):r.onSuccess(n.data),void delete t.requests_[n.reqID.toString()])},this.client_.net_=new WebSocket(this.client_.netArgs_),t.net_.haserror=!1,t.net_.binaryType="arraybuffer",t.net_.onmessage=function(e){t.normalOnMessage_(e.data)};var e=setTimeout(function(){t.net_.timeout()},1e3*t.connectTimeout_),n=this;t.net_.onopen=function(r){null!=e&&(clearTimeout(e),e=null),n.sendAllRequest(),t.protocol_.onOpen(t.onConnectionSuc_)},t.net_.onclose=function(r){null!=e&&(clearTimeout(e),e=null),t.net_.close(1e3),t.protocol_.onClose(),t.net_.haserror||(t.net_.haserror=!1,n.netError("connection closed by peer or connection error"))},t.net_.onerror=function(r){t.net_.haserror=!0,null!=e&&(clearTimeout(e),e=null),n.netError("connect error---"+JSON.stringify(r))},t.net_.timeout=function(r){e=null,this.onopen=function(t){},this.onclose=function(t){},this.onerror=function(t){},this.onmessage=function(t){},t.net_=null,n.netError("connect timeout")}},c.sendAllRequest=function(){var t=this.client_;for(var e in t.requests_)this.sendRequest(t.requests_[e])},c.errorAllRequest=function(t){var e=this.client_;for(var n in e.requests_)!function(n){o(function(){e.normalOnMessage_(e.protocol_.buildFailedMessage(t,n))})}(Number(n))},c.netError=function(t){var e=this.client_;this.errorAllRequest(t),e.onConnectionFaild_(t)};var l=t.stm=t.stm||{};l.Client=n}(this); -------------------------------------------------------------------------------- /client/js/dest/stringview.min.js: -------------------------------------------------------------------------------- 1 | !function(e){"use strict";function t(e,r,n,a){var i,o,h,s,c,f,g=isFinite(n)?n:0,u=15;r&&(this.encoding=r.toString());e:switch(this.encoding){case"UTF-8":s=t.putUTF8CharCode,c=t.getUTF8CharLength,i=Uint8Array;break e;case"UTF-16":s=t.putUTF16CharCode,c=t.getUTF16CharLength,i=Uint16Array;break e;case"UTF-32":i=Uint32Array,u&=14;break e;default:i=Uint8Array,u&=14}e:switch(typeof e){case"string":u&=7;break e;case"object":switch(e.constructor){case t:u&=3;break e;case String:u&=7;break e;case ArrayBuffer:o=new i(e),f="UTF-32"===this.encoding?e.byteLength>>>2:"UTF-16"===this.encoding?e.byteLength>>>1:e.byteLength,h=0!==g||isFinite(a)&&a!==f?new i(e,g,isFinite(a)?a:f-g):o;break e;case Uint32Array:case Uint16Array:case Uint8Array:i=e.constructor,f=e.length,o=0===e.byteOffset&&e.length===(i===Uint32Array?e.buffer.byteLength>>>2:i===Uint16Array?e.buffer.byteLength>>>1:e.buffer.byteLength)?e:new i(e.buffer),h=0!==g||isFinite(a)&&a!==f?e.subarray(g,isFinite(a)?g+a:f):e;break e;default:o=new i(e),f=o.length,h=0!==g||isFinite(a)&&a!==f?o.subarray(g,isFinite(a)?g+a:f):o}break e;default:o=h=new i(Number(e)||0)}if(u<8){var d,U,F,b,T,l,C;4&u?(d=e,U=f=d.length,u^="UTF-32"===this.encoding?0:2,g=F=n?Math.max((U+n)%U,0):0,T=b=(Number.isInteger(a)?Math.min(Math.max(a,0)+g,U):U)-1):(d=e.rawData,f=e.makeIndex(),g=F=n?Math.max((f+n)%f,0):0,U=Number.isInteger(a)?Math.min(Math.max(a,0),f-F):f,T=b=U+F,"UTF-8"===e.encoding?(l=t.getUTF8CharLength,C=t.loadUTF8CharCode):"UTF-16"===e.encoding?(l=t.getUTF16CharLength,C=t.loadUTF16CharCode):u&=1),(0===U||u<4&&d.encoding===this.encoding&&0===F&&U===f)&&(u=7);e:switch(u){case 0:o=new i(U);for(var w=0;wF&&(U+=c(m));o=new i(U);for(var y=g,w=0;w3&&(g>0||T-9007199254740992&&e<9007199254740992&&Math.floor(e)===e}),t.loadUTF8CharCode=function(e,t){var r=e.length,n=e[t];return n>251&&n<254&&t+5247&&n<252&&t+4239&&n<248&&t+3223&&n<240&&t+2191&&n<224&&t+1>>6),e[n++]=128+(63&t)):t<65536?(e[n++]=224+(t>>>12),e[n++]=128+(t>>>6&63),e[n++]=128+(63&t)):t<2097152?(e[n++]=240+(t>>>18),e[n++]=128+(t>>>12&63),e[n++]=128+(t>>>6&63),e[n++]=128+(63&t)):t<67108864?(e[n++]=248+(t>>>24),e[n++]=128+(t>>>18&63),e[n++]=128+(t>>>12&63),e[n++]=128+(t>>>6&63),e[n++]=128+(63&t)):(e[n++]=252+t/1073741824,e[n++]=128+(t>>>24&63),e[n++]=128+(t>>>18&63),e[n++]=128+(t>>>12&63),e[n++]=128+(t>>>6&63),e[n++]=128+(63&t)),n},t.getUTF8CharLength=function(e){return e<128?1:e<2048?2:e<65536?3:e<2097152?4:e<67108864?5:6},t.loadUTF16CharCode=function(e,t){var r=e[t];return r>55231&&t+1>>10),e[n++]=56320+(1023&t)),n},t.getUTF16CharLength=function(e){return e<65536?1:2},t.b64ToUint6=function(e){return e>64&&e<91?e-65:e>96&&e<123?e-71:e>47&&e<58?e+4:43===e?62:47===e?63:0},t.uint6ToB64=function(e){return e<26?e+65:e<52?e+71:e<62?e-4:62===e?43:63===e?47:65},t.bytesToBase64=function(e){for(var r,n="",a=e.length,i=0,o=0;o>>r&24),2!==r&&e.length-o!==1||(n+=String.fromCharCode(t.uint6ToB64(i>>>18&63),t.uint6ToB64(i>>>12&63),t.uint6ToB64(i>>>6&63),t.uint6ToB64(63&i)),i=0);return n.replace(/A(?=A$|$)/g,"=")},t.base64ToBytes=function(e,r){for(var n,a,i=e.replace(/[^A-Za-z0-9\+\/]/g,""),o=i.length,h=r?Math.ceil((3*o+1>>>2)/r)*r:3*o+1>>>2,s=new Uint8Array(h),c=0,f=0,g=0;g>>(16>>>n&24)&255;c=0}return s},t.makeFromBase64=function(e,r,n,a){return new t("UTF-16"===r||"UTF-32"===r?t.base64ToBytes(e,"UTF-16"===r?2:4).buffer:t.base64ToBytes(e),r,n,a)},t.prototype.encoding="UTF-8",t.prototype.makeIndex=function(e,t){var r,n=this.rawData,a=n.length,i=t||0,o=i,h=isNaN(e)?1/0:e;if(e+1>n.length)throw new RangeError("StringView.prototype.makeIndex - The offset can't be major than the length of the array - 1.");switch(this.encoding){case"UTF-8":var s;for(r=0;o251&&s<254&&o+5247&&s<252&&o+4239&&s<248&&o+3223&&s<240&&o+2191&&s<224&&o+155231&&o+1o?o-a:r:o,0===a&&i===o?this:(h?(s=this.makeIndex(a),n=this.makeIndex(i,s)-s):(s=a,n=i-a),"UTF-16"===this.encoding?s<<=1:"UTF-32"===this.encoding&&(s<<=2),new t(this.buffer,this.encoding,s,n)))},t.prototype.forEachChar=function(e,r,n,a){var i,o,h=this.rawData;if("UTF-8"===this.encoding||"UTF-16"===this.encoding){var s,c;"UTF-8"===this.encoding?(s=t.getUTF8CharLength,c=t.loadUTF8CharCode):"UTF-16"===this.encoding&&(s=t.getUTF16CharLength,c=t.loadUTF16CharCode),o=isFinite(n)?this.makeIndex(n):0,i=isFinite(a)?this.makeIndex(a,o):h.length;for(var f,g=0;o"); 216 | return; 217 | } 218 | 219 | request.onComplete(); 220 | if (response.state != stm.Response.State.Success) { 221 | if (response.data === null || response.data === undefined) { 222 | request.onFailed("may be server error, but server has closed the error log"); 223 | } else { 224 | request.onFailed((new StringView(response.data)).toString()); 225 | } 226 | } else { 227 | request.onSuccess(response.data); 228 | } 229 | delete client.requests_[response.reqID.toString()]; 230 | }; 231 | 232 | this.client_.net_ = new WebSocket(this.client_.netArgs_); 233 | client.net_.haserror = false; // 添加一项WebSocket没有的属性 234 | client.net_.binaryType = "arraybuffer"; 235 | client.net_.onmessage = function (event) { 236 | client.normalOnMessage_(event.data); 237 | }; 238 | 239 | var timer = setTimeout(function(){ 240 | client.net_.timeout(); 241 | }, client.connectTimeout_*1000); 242 | 243 | var that = this; 244 | client.net_.onopen = function(event){ 245 | if (timer != null) { 246 | clearTimeout(timer); 247 | timer = null; 248 | } 249 | 250 | that.sendAllRequest(); 251 | client.protocol_.onOpen(client.onConnectionSuc_); 252 | }; 253 | 254 | client.net_.onclose = function(event) { 255 | if (timer != null) { 256 | clearTimeout(timer); 257 | timer = null; 258 | } 259 | // readyState 的状态改变会先于onclose的执行 260 | // if (client.net_.readyState != WebSocket.OPEN) { 261 | // return; 262 | // } 263 | client.net_.close(1000); 264 | client.protocol_.onClose(); 265 | if (!client.net_.haserror) { 266 | client.net_.haserror = false; 267 | that.netError("connection closed by peer or connection error"); 268 | } 269 | }; 270 | 271 | client.net_.onerror = function(event) { 272 | // 部分错误可能会自动调用 onclose 273 | client.net_.haserror = true; 274 | 275 | if (timer != null) { 276 | clearTimeout(timer); 277 | timer = null; 278 | } 279 | 280 | that.netError("connect error---" + JSON.stringify(event)); 281 | }; 282 | 283 | client.net_.timeout = function(event) { 284 | timer = null; 285 | this.onopen = function(event){}; 286 | this.onclose = function(event){}; 287 | this.onerror = function(event){}; 288 | this.onmessage = function(event){}; 289 | client.net_ = null; 290 | 291 | that.netError("connect timeout"); 292 | }; 293 | 294 | }; 295 | 296 | privatePro.sendAllRequest = function () { 297 | var client = this.client_; 298 | for (var req in client.requests_) { 299 | this.sendRequest(client.requests_[req]); 300 | } 301 | }; 302 | 303 | privatePro.errorAllRequest = function (error) { 304 | var client = this.client_; 305 | for (var req in client.requests_) { 306 | (function (id) { 307 | postTask(function () { 308 | client.normalOnMessage_(client.protocol_.buildFailedMessage(error, id)); 309 | }); 310 | })(Number(req)); 311 | } 312 | }; 313 | 314 | privatePro.netError = function (errorstr) { 315 | var client = this.client_; 316 | 317 | this.errorAllRequest(errorstr); 318 | 319 | client.onConnectionFaild_(errorstr); 320 | }; 321 | 322 | var stm = ns.stm = ns.stm || {}; 323 | stm.Client = Client; 324 | 325 | })(this); 326 | -------------------------------------------------------------------------------- /client/js/stm.contentprotocol.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xpwu on 2016/12/1. 3 | */ 4 | 5 | (function (ns) { 6 | "use strict"; 7 | 8 | var stm = ns.stm = ns.stm || {}; 9 | 10 | stm.ContentProtocol = { 11 | /** 12 | * 13 | * @param {function()}callback 14 | */ 15 | onOpen: function (callback) { 16 | callback(); 17 | } 18 | 19 | /** 20 | * 21 | */ 22 | , onClose: function () { 23 | 24 | } 25 | 26 | /** 27 | * 28 | * @param {ArrayBuffer}message 29 | * @return {*|Response} 30 | */ 31 | , parse: function (message) { 32 | return new stm.Response(); 33 | } 34 | 35 | /** 36 | * 37 | * @param {ArrayBuffer|string|null}body 38 | * @param {Object|null}headers 39 | * @param {number}reqID 40 | * @return {ArrayBuffer|string} success:ArrayBuffer; error: string 41 | */ 42 | , build: function (body, headers, reqID) { 43 | return new ArrayBuffer(2); 44 | } 45 | 46 | /** 47 | * 48 | * @param {string}error 49 | * @param {number}reqID 50 | * @return {ArrayBuffer} 51 | */ 52 | , buildFailedMessage: function(error, reqID) { 53 | return new ArrayBuffer(2); 54 | } 55 | 56 | , extend: function(child) { 57 | if (child.__proto__) { 58 | child.__proto__ = this; 59 | } else { 60 | for (var propertyName in this) { 61 | if (this.hasOwnProperty(propertyName) 62 | && !child.hasOwnProperty(propertyName)) { 63 | child[propertyName] = this[propertyName]; 64 | } 65 | } 66 | 67 | // IE won't copy toString using the loop above 68 | if (this.hasOwnProperty('toString') 69 | && !child.hasOwnProperty('toString')) { 70 | child.toString = this.toString; 71 | } 72 | } 73 | child.$parent = this; 74 | 75 | return child; 76 | } 77 | }; 78 | 79 | })(this); -------------------------------------------------------------------------------- /client/js/stm.defaultcontentprotocol.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xpwu on 2016/12/1. 3 | */ 4 | 5 | 6 | (function (ns) { 7 | "use strict"; 8 | var stm = ns.stm = ns.stm || {}; 9 | 10 | stm.DefaultContentProtocol = { 11 | /** 12 | * 13 | * @param {ArrayBuffer} message 14 | * @return {*|Response} 15 | */ 16 | parse: function (message) { 17 | var response = new stm.Response(); 18 | var messageView = new DataView(message); 19 | response.reqID = messageView.getUint32(0); 20 | response.state = (messageView.getUint8(4) == 0)? stm.Response.State.Success 21 | : stm.Response.State.Failed; 22 | response.data = message.slice(5); 23 | 24 | return response; 25 | } 26 | 27 | /** 28 | * 29 | * @param {ArrayBuffer|string|null}body 30 | * @param {Object|null}headers 31 | * @param {number}reqID 32 | * @return {ArrayBuffer|string} 33 | */ 34 | , build: function (body, headers, reqID) { 35 | body = body || ""; 36 | if (typeof body !== "string" && !(body instanceof ArrayBuffer)) { 37 | return "body type is error, must be string or ArrayBuffer"; 38 | } 39 | 40 | headers = headers || {}; 41 | if (typeof headers !== "object") { 42 | return "headers must be a object type, for example {uri: '/location'}"; 43 | } 44 | 45 | var headerLen = 0; 46 | for (var key in headers) { 47 | if (!headers.hasOwnProperty(key)) { 48 | continue; 49 | } 50 | if (typeof key !== "string" || typeof headers[key] !== "string") { 51 | return "headers' key or property must be string"; 52 | } 53 | 54 | if (key.length > 255) { 55 | return "length of headers' key <" + key + "> more than 255"; 56 | } 57 | if (headers[key].length > 255) { 58 | return "length of headers' object <" + headers[key] + "> more than 255"; 59 | } 60 | 61 | if (key.length == 0 || headers[key].length == 0) { 62 | continue; 63 | } 64 | headerLen += 1 + 1 + key.length + headers[key].length; 65 | } 66 | 67 | body = new StringView(body); 68 | var buffer = new ArrayBuffer(4 + body.rawData.byteLength + 1 + headerLen); 69 | (new DataView(buffer)).setUint32(0, reqID); 70 | 71 | var pos = 4; 72 | for (key in headers) { 73 | if (!headers.hasOwnProperty(key)) { 74 | continue; 75 | } 76 | 77 | (new DataView(buffer)).setUint8(pos, key.length); 78 | pos++; 79 | (new Uint8Array(buffer)).set((new StringView(key)).rawData, pos); 80 | pos += key.length; 81 | (new DataView(buffer)).setUint8(pos, headers[key].length); 82 | pos++; 83 | (new Uint8Array(buffer)).set((new StringView(headers[key])).rawData, pos); 84 | pos += headers[key].length; 85 | } 86 | (new DataView(buffer)).setUint8(pos, 0); 87 | pos++; 88 | 89 | (new Uint8Array(buffer)).set(body.rawData, pos); 90 | 91 | return buffer; 92 | } 93 | 94 | /** 95 | * 96 | * @param {string}error 97 | * @param {number}reqID 98 | * @return {ArrayBuffer} 99 | */ 100 | , buildFailedMessage: function(error, reqID) { 101 | 102 | error = new StringView(error); 103 | var buffer = new ArrayBuffer(4 + error.rawData.byteLength + 1); 104 | (new DataView(buffer)).setUint32(0, reqID); 105 | (new DataView(buffer)).setUint8(4, stm.Response.State.Failed); 106 | (new Uint8Array(buffer)).set(error.rawData, 5); 107 | 108 | return buffer; 109 | } 110 | 111 | }; 112 | 113 | })(this); 114 | -------------------------------------------------------------------------------- /client/js/stm.response.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xpwu on 2016/12/1. 3 | */ 4 | 5 | 6 | (function (ns) { 7 | "use strict"; 8 | 9 | var stm = ns.stm = ns.stm || {}; 10 | 11 | var state = {Success: 0, Failed: 1}; 12 | 13 | function Response() { 14 | /** 15 | * 16 | * @type {number} 17 | */ 18 | this.reqID = 0; 19 | /** 20 | * 21 | * @type {number} 22 | */ 23 | this.state = state.Success; 24 | /** 25 | * 26 | * @type {ArrayBuffer} 27 | */ 28 | this.data = null; 29 | } 30 | 31 | stm.Response = Response; 32 | stm.Response.State = state; 33 | 34 | })(this); -------------------------------------------------------------------------------- /client/js/test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | test js 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |

this is only test stm.client.

19 | 110 | 111 | -------------------------------------------------------------------------------- /client/js/test/test.min.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | test js 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

this is only test stm.client.min

16 | 119 | 120 | -------------------------------------------------------------------------------- /client/js/test/test.ssl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | test ssl js 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |

this is only test stm.client.ssl

19 | 122 | 123 | -------------------------------------------------------------------------------- /client/wxapp/.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /client/wxapp/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /client/wxapp/app.js: -------------------------------------------------------------------------------- 1 | 2 | let stm = require("stm/client.js"); 3 | let es6Client = require("stm/client.es6").Client; 4 | 5 | App({ 6 | onLaunch: function() { 7 | this.client = new stm.Client(); 8 | this.client.setConnectArgs("ws://127.0.0.1:8001", function(){ 9 | console.log("connect success"); 10 | } 11 | , function(str){ 12 | console.error(str); 13 | }); 14 | this.client.onPush = function(data) { 15 | console.log(new stm.Client.StringView(data).toString()); 16 | }; 17 | 18 | this.es6Client = new es6Client(); 19 | this.es6Client.setConnectArgs("ws://127.0.0.1:8001") 20 | .then(()=>console.log("es6 connect success")) 21 | .catch((error)=>{ 22 | console.error(error); 23 | }) 24 | }, 25 | 26 | /** 27 | * @type stm.Client 28 | */ 29 | client: null, 30 | 31 | es6Client: null 32 | 33 | }) -------------------------------------------------------------------------------- /client/wxapp/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/index" 4 | ] 5 | } -------------------------------------------------------------------------------- /client/wxapp/app.wxss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xpwu/ngx-stream-request-module/a1d1d46e31844142c22e12e76606e9fb13540eac/client/wxapp/app.wxss -------------------------------------------------------------------------------- /client/wxapp/pages/index.js: -------------------------------------------------------------------------------- 1 | 2 | let stm = require("../stm/client.js"); 3 | 4 | 5 | // /pages/index.js 6 | Page({ 7 | data:{}, 8 | onLoad:function(options){ 9 | // 页面初始化 options为页面跳转所带来的参数 10 | }, 11 | onReady:function(){ 12 | // 页面渲染完成 13 | getApp().client.addRequest("test", function (data) { 14 | console.log(new stm.Client.StringView(data).toString()); 15 | }, {api:'/API/GetInfo'}, function (res) { 16 | console.error(res); 17 | }, function () { 18 | console.log("complete"); 19 | }); 20 | 21 | getApp().es6Client.addJsonRequest("test", {api:'/API/GetInfo'}) 22 | .then((res)=>{ 23 | console.log(res); 24 | }).catch((error)=>{ 25 | console.error(error); 26 | }); 27 | }, 28 | onShow:function(){ 29 | // 页面显示 30 | getApp().client.addRequest("test", function (data) { 31 | console.log(new stm.Client.StringView(data).toString()); 32 | }, { api:'/API/GetInfo'}, function (res) { 33 | console.error(res); 34 | }, function () { 35 | console.log("complete"); 36 | }); 37 | 38 | getApp().es6Client.addJsonRequest("test", {api:'/API/GetInfo'}) 39 | .then((res)=>{ 40 | console.log(res); 41 | }).catch((error)=>{ 42 | console.error(error); 43 | }); 44 | }, 45 | onHide:function(){ 46 | // 页面隐藏 47 | }, 48 | onUnload:function(){ 49 | // 页面关闭 50 | } 51 | }) 52 | 53 | -------------------------------------------------------------------------------- /client/wxapp/pages/index.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /client/wxapp/pages/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | /pages/index.wxml 3 | -------------------------------------------------------------------------------- /client/wxapp/pages/index.wxss: -------------------------------------------------------------------------------- 1 | /* /pages/index.wxss */ -------------------------------------------------------------------------------- /client/wxapp/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件。", 3 | "setting": { 4 | "urlCheck": false, 5 | "es6": true, 6 | "postcss": true, 7 | "minified": true, 8 | "newFeature": true 9 | }, 10 | "compileType": "miniprogram", 11 | "libVersion": "1.7.0", 12 | "appid": "wx7b2a9c041288294f", 13 | "projectname": "stm-test", 14 | "condition": { 15 | "search": { 16 | "current": -1, 17 | "list": [] 18 | }, 19 | "conversation": { 20 | "current": -1, 21 | "list": [] 22 | }, 23 | "miniprogram": { 24 | "current": -1, 25 | "list": [] 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /client/wxapp/stm/client.es6.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | let ClientImpl = require("client").Client; 5 | 6 | 7 | class Client { 8 | constructor() { 9 | /** 10 | * 11 | * @type {Client} 12 | * @private 13 | */ 14 | this.impl_ = new ClientImpl(); 15 | } 16 | 17 | /** 18 | * 19 | * @return {Promise.} 20 | */ 21 | pushJson() { 22 | return new Promise((resolve)=>{ 23 | this.impl_.onPushJson = function (json) { 24 | resolve(json); 25 | } 26 | }); 27 | } 28 | 29 | /** 30 | * 31 | * @param {number} connectTimeout unit: s 32 | */ 33 | setConfig(connectTimeout) { 34 | this.impl_.setConfig(connectTimeout); 35 | } 36 | 37 | /** 38 | * 39 | * @param {string}args ws(s)://xxxxx:xx 40 | * @return {Promise.} 41 | */ 42 | setConnectArgs(args) { 43 | return new Promise((resolve, reject)=>{ 44 | this.impl_.setConnectArgs(args, ()=>{ 45 | resolve(); 46 | }, (error)=>{ 47 | reject(error); 48 | }) 49 | }); 50 | } 51 | 52 | /** 53 | * 54 | * @param {{}|null}body 55 | * @param {{}|null}headers 56 | * @return {Promise.} 57 | */ 58 | addJsonRequest(body, headers) { 59 | return new Promise((resolve, reject)=>{ 60 | this.impl_.addJsonRequest(body, (res)=>{ 61 | resolve(res); 62 | }, headers 63 | , (error)=>{ 64 | reject(error); 65 | }, null); 66 | }); 67 | } 68 | 69 | // /** 70 | // * 71 | // * @param {ArrayBuffer|string|null}body 72 | // * @param {{}|null}headers 73 | // * @return {Promise.} 74 | // */ 75 | // addRequest(body, headers) { 76 | // return new Promise((resolve, reject)=>{ 77 | // this.impl_.addRequest(body, (res)=>{ 78 | // resolve(res); 79 | // }, headers 80 | // , (error)=>{ 81 | // reject(error); 82 | // }); 83 | // }) 84 | // } 85 | } 86 | 87 | module.exports.Client = Client; 88 | -------------------------------------------------------------------------------- /client/wxapp/stm/contentprotocol.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xpwu on 2016/12/1. 3 | */ 4 | 5 | // (function (ns) { 6 | // "use strict"; 7 | 8 | // var stm = ns.stm = ns.stm || {}; 9 | 10 | let ContentProtocol = { 11 | /** 12 | * 13 | * @param {function()}callback 14 | */ 15 | onOpen: function (callback) { 16 | callback(); 17 | } 18 | 19 | /** 20 | * 21 | */ 22 | , onClose: function () { 23 | 24 | } 25 | 26 | /** 27 | * 28 | * @param {ArrayBuffer}message 29 | * @return {*|Response} 30 | */ 31 | , parse: function (message) { 32 | return new stm.Response(); 33 | } 34 | 35 | /** 36 | * 37 | * @param {ArrayBuffer|string|null}body 38 | * @param {Object|null}headers 39 | * @param {number}reqID 40 | * @return {ArrayBuffer|string} success:ArrayBuffer; error: string 41 | */ 42 | , build: function (body, headers, reqID) { 43 | return new ArrayBuffer(2); 44 | } 45 | 46 | /** 47 | * 48 | * @param {string}error 49 | * @param {number}reqID 50 | * @return {ArrayBuffer} 51 | */ 52 | , buildFailedMessage: function(error, reqID) { 53 | return new ArrayBuffer(2); 54 | } 55 | 56 | , extend: function(child) { 57 | if (child.__proto__) { 58 | child.__proto__ = this; 59 | } else { 60 | for (var propertyName in this) { 61 | if (this.hasOwnProperty(propertyName) 62 | && !child.hasOwnProperty(propertyName)) { 63 | child[propertyName] = this[propertyName]; 64 | } 65 | } 66 | 67 | // IE won't copy toString using the loop above 68 | if (this.hasOwnProperty('toString') 69 | && !child.hasOwnProperty('toString')) { 70 | child.toString = this.toString; 71 | } 72 | } 73 | child.$parent = this; 74 | 75 | return child; 76 | } 77 | }; 78 | 79 | module.exports.ContentProtocol = ContentProtocol; 80 | 81 | // })(this); -------------------------------------------------------------------------------- /client/wxapp/stm/defaultcontentprotocol.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xpwu on 2016/12/1. 3 | */ 4 | 5 | 6 | // (function (ns) { 7 | // "use strict"; 8 | // var stm = ns.stm = ns.stm || {}; 9 | 10 | let StringView = require("stringview.js").StringView; 11 | let Response = require("response.js").Response; 12 | let WXWebSocket = require("wxwebsocket.js").WXWebSocket; 13 | 14 | let stm={}; 15 | stm.Response = Response; 16 | stm.StringView = StringView; 17 | 18 | let DefaultContentProtocol = { 19 | /** 20 | * 21 | * @param {ArrayBuffer} message 22 | * @return {*|Response} 23 | */ 24 | parse: function (message) { 25 | var response = new stm.Response(); 26 | var messageView = new DataView(message); 27 | response.reqID = messageView.getUint32(0); 28 | response.state = (messageView.getUint8(4) == 0)? stm.Response.State.Success 29 | : stm.Response.State.Failed; 30 | response.data = message.slice(5); 31 | 32 | return response; 33 | } 34 | 35 | /** 36 | * 37 | * @param {ArrayBuffer|string|null}body 38 | * @param {Object|null}headers 39 | * @param {number}reqID 40 | * @return {ArrayBuffer|string} 41 | */ 42 | , build: function (body, headers, reqID) { 43 | body = body || ""; 44 | if (typeof body !== "string" && !(body instanceof ArrayBuffer)) { 45 | return "body type is error, must be string or ArrayBuffer"; 46 | } 47 | 48 | headers = headers || {}; 49 | if (typeof headers !== "object") { 50 | return "headers must be a object type, for example {uri: '/location'}"; 51 | } 52 | 53 | var headerLen = 0; 54 | for (var key in headers) { 55 | if (!headers.hasOwnProperty(key)) { 56 | continue; 57 | } 58 | if (typeof key !== "string" || typeof headers[key] !== "string") { 59 | return "headers' key or property must be string"; 60 | } 61 | 62 | if (key.length > 255) { 63 | return "length of headers' key <" + key + "> more than 255"; 64 | } 65 | if (headers[key].length > 255) { 66 | return "length of headers' object <" + headers[key] + "> more than 255"; 67 | } 68 | 69 | if (key.length == 0 || headers[key].length == 0) { 70 | continue; 71 | } 72 | headerLen += 1 + 1 + key.length + headers[key].length; 73 | } 74 | 75 | body = new StringView(body); 76 | var buffer = new ArrayBuffer(4 + body.rawData.byteLength + 1 + headerLen); 77 | (new DataView(buffer)).setUint32(0, reqID); 78 | 79 | var pos = 4; 80 | for (key in headers) { 81 | if (!headers.hasOwnProperty(key)) { 82 | continue; 83 | } 84 | 85 | (new DataView(buffer)).setUint8(pos, key.length); 86 | pos++; 87 | (new Uint8Array(buffer)).set((new StringView(key)).rawData, pos); 88 | pos += key.length; 89 | (new DataView(buffer)).setUint8(pos, headers[key].length); 90 | pos++; 91 | (new Uint8Array(buffer)).set((new StringView(headers[key])).rawData, pos); 92 | pos += headers[key].length; 93 | } 94 | (new DataView(buffer)).setUint8(pos, 0); 95 | pos++; 96 | 97 | (new Uint8Array(buffer)).set(body.rawData, pos); 98 | 99 | return buffer; 100 | } 101 | 102 | /** 103 | * 104 | * @param {string}error 105 | * @param {number}reqID 106 | * @return {ArrayBuffer} 107 | */ 108 | , buildFailedMessage: function(error, reqID) { 109 | 110 | error = new StringView(error); 111 | var buffer = new ArrayBuffer(4 + error.rawData.byteLength + 1); 112 | (new DataView(buffer)).setUint32(0, reqID); 113 | (new DataView(buffer)).setUint8(4, stm.Response.State.Failed); 114 | (new Uint8Array(buffer)).set(error.rawData, 5); 115 | 116 | return buffer; 117 | } 118 | 119 | }; 120 | 121 | module.exports.DefaultContentProtocol = DefaultContentProtocol; 122 | 123 | // })(this); 124 | -------------------------------------------------------------------------------- /client/wxapp/stm/response.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xpwu on 2016/12/1. 3 | */ 4 | 5 | 6 | // (function (ns) { 7 | // "use strict"; 8 | 9 | // var stm = ns.stm = ns.stm || {}; 10 | 11 | var state = {Success: 0, Failed: 1}; 12 | 13 | function Response() { 14 | /** 15 | * 16 | * @type {number} 17 | */ 18 | this.reqID = 0; 19 | /** 20 | * 21 | * @type {number} 22 | */ 23 | this.state = state.Success; 24 | /** 25 | * 26 | * @type {ArrayBuffer} 27 | */ 28 | this.data = null; 29 | } 30 | 31 | // stm.Response = Response; 32 | // stm.Response.State = state; 33 | 34 | module.exports.Response = Response; 35 | module.exports.Response.State = state; 36 | 37 | // })(this); -------------------------------------------------------------------------------- /client/wxapp/stm/wxwebsocket.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | function TranVersion(vstr) { 4 | let ver = vstr.split("."); 5 | let version = 0; 6 | let factor = 1; 7 | for(let i = ver.length; i > 0; --i) { 8 | version += ver[i-1] * factor; 9 | factor *= 100; 10 | } 11 | 12 | return version; 13 | } 14 | 15 | class WxWebSocketImpl { 16 | constructor() { 17 | this.onmessage = function(data){}; 18 | this.onopen = function(data){}; 19 | this.onclose = function(data){}; 20 | this.onerror = function(data){}; 21 | 22 | this.readyState = WXWebSocket.CONNECTING; 23 | } 24 | 25 | /** 26 | @param {String|ArrayBuffer|ArrayBufferView|Blob} msg 27 | */ 28 | send(msg){} 29 | 30 | /** 31 | @param {number} [code] 32 | @param {string} [reason] 33 | */ 34 | close(code, reason){} 35 | } 36 | 37 | class WxWebSocketImplless170 extends WxWebSocketImpl { 38 | constructor(url) { 39 | super(); 40 | 41 | wx.connectSocket({ 42 | url: url 43 | }); 44 | 45 | wx.onSocketOpen((res)=>{ 46 | this.readyState = WXWebSocket.OPEN; 47 | this.onopen(res); 48 | }); 49 | 50 | wx.onSocketError((res)=>{ 51 | this.readyState = WXWebSocket.CLOSED; 52 | this.onerror(res); 53 | }); 54 | 55 | wx.onSocketMessage((res)=>{ 56 | this.onmessage(res); 57 | }); 58 | 59 | wx.onSocketClose((res)=>{ 60 | this.readyState = WXWebSocket.CLOSED; 61 | this.onclose(res); 62 | }); 63 | } 64 | 65 | send(msg) { 66 | wx.sendSocketMessage({ 67 | data: msg 68 | }); 69 | } 70 | 71 | close(code,reason) { 72 | wx.closeSocket({code:code, reason:reason}); 73 | }; 74 | } 75 | 76 | class WxWebSocketImpl170 extends WxWebSocketImpl { 77 | constructor(url) { 78 | super(); 79 | 80 | this.task = wx.connectSocket({ 81 | url: url 82 | }); 83 | 84 | this.task.onOpen((res)=>{ 85 | this.readyState = WXWebSocket.OPEN; 86 | this.onopen(res); 87 | }); 88 | 89 | this.task.onClose((res)=>{ 90 | this.readyState = WXWebSocket.CLOSED; 91 | this.onclose(res); 92 | }); 93 | 94 | this.task.onError((res)=>{ 95 | this.readyState = WXWebSocket.CLOSED; 96 | this.onerror(res); 97 | }); 98 | 99 | this.task.onMessage((res)=>{ 100 | this.onmessage(res); 101 | }); 102 | } 103 | 104 | send(msg) { 105 | this.task.send({ 106 | data: msg 107 | }); 108 | } 109 | 110 | close(code,reason) { 111 | this.task.close({code:code, reason:reason}); 112 | }; 113 | } 114 | 115 | 116 | class WXWebSocket { 117 | 118 | constructor(url) { 119 | let res = wx.getSystemInfoSync(); 120 | if (res.SDKVersion && TranVersion(res.SDKVersion) >= 10700) { 121 | this.impl_ = new WxWebSocketImpl170(url); 122 | } else { 123 | this.impl_ = new WxWebSocketImplless170(url); 124 | } 125 | } 126 | 127 | set onmessage(f) { 128 | this.impl_.onmessage = f; 129 | } 130 | 131 | set onopen(f) { 132 | this.impl_.onopen = f; 133 | } 134 | 135 | set onclose(f) { 136 | this.impl_.onclose = f; 137 | } 138 | 139 | set onerror(f) { 140 | this.impl_.onerror = f; 141 | } 142 | 143 | get readyState() { 144 | return this.impl_.readyState; 145 | } 146 | 147 | /** 148 | @param {String|ArrayBuffer|ArrayBufferView|Blob} msg 149 | */ 150 | send(msg) { 151 | this.impl_.send(msg); 152 | }; 153 | 154 | /** 155 | @param {number} [code] 156 | @param {string} [reason] 157 | */ 158 | close(code,reason) { 159 | this.impl_.close(code, reason); 160 | }; 161 | } 162 | 163 | /** 164 | @static 165 | @type {number} 166 | @const 167 | */ 168 | WXWebSocket.CONNECTING = 0; 169 | /** 170 | @static 171 | @type {number} 172 | @const 173 | */ 174 | WXWebSocket.OPEN = 1; 175 | /** 176 | @static 177 | @type {number} 178 | @const 179 | */ 180 | WXWebSocket.CLOSING = 2; 181 | /** 182 | @static 183 | @type {number} 184 | @const 185 | */ 186 | WXWebSocket.CLOSED = 3; 187 | 188 | 189 | module.exports.WXWebSocket = WXWebSocket; 190 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | #user nobody; 3 | worker_processes 4; 4 | 5 | #error_log logs/error.log; 6 | #error_log logs/error.log notice; 7 | #error_log logs/error.log info; 8 | 9 | #pid logs/nginx.pid; 10 | 11 | #daemon off; 12 | #master_process off; 13 | 14 | events { 15 | worker_connections 1024; 16 | } 17 | 18 | 19 | http { 20 | include mime.types; 21 | default_type application/octet-stream; 22 | 23 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 24 | # '$status $body_bytes_sent "$http_referer" ' 25 | # '"$http_user_agent" "$http_x_forwarded_for"'; 26 | 27 | #access_log logs/access.log main; 28 | 29 | sendfile on; 30 | #tcp_nopush on; 31 | 32 | #keepalive_timeout 0; 33 | keepalive_timeout 65; 34 | 35 | #gzip on; 36 | 37 | server { 38 | listen 10000; 39 | server_name localhost; 40 | 41 | #charset koi8-r; 42 | 43 | #access_log logs/host.access.log main; 44 | 45 | location / { 46 | root html; 47 | index index.html index.htm; 48 | add_header Test-Http-pr "text/plain;charset=utf-8"; 49 | return 200 "this is test"; 50 | } 51 | 52 | #error_page 404 /404.html; 53 | 54 | # redirect server error pages to the static page /50x.html 55 | # 56 | error_page 500 502 503 504 /50x.html; 57 | location = /50x.html { 58 | root html; 59 | } 60 | 61 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 62 | # 63 | #location ~ \.php$ { 64 | # proxy_pass http://127.0.0.1; 65 | #} 66 | 67 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 68 | # 69 | #location ~ \.php$ { 70 | # root html; 71 | # fastcgi_pass 127.0.0.1:9000; 72 | # fastcgi_index index.php; 73 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 74 | # include fastcgi_params; 75 | #} 76 | 77 | # deny access to .htaccess files, if Apache's document root 78 | # concurs with nginx's one 79 | # 80 | #location ~ /\.ht { 81 | # deny all; 82 | #} 83 | } 84 | 85 | 86 | # another virtual host using mix of IP-, name-, and port-based configuration 87 | # 88 | #server { 89 | # listen 8000; 90 | # listen somename:8080; 91 | # server_name somename alias another.alias; 92 | 93 | # location / { 94 | # root html; 95 | # index index.html index.htm; 96 | # } 97 | #} 98 | 99 | 100 | # HTTPS server 101 | # 102 | #server { 103 | # listen 443 ssl; 104 | # server_name localhost; 105 | 106 | # ssl_certificate cert.pem; 107 | # ssl_certificate_key cert.key; 108 | 109 | # ssl_session_cache shared:SSL:1m; 110 | # ssl_session_timeout 5m; 111 | 112 | # ssl_ciphers HIGH:!aNULL:!MD5; 113 | # ssl_prefer_server_ciphers on; 114 | 115 | # location / { 116 | # root html; 117 | # index index.html index.htm; 118 | # } 119 | #} 120 | } 121 | 122 | stream { 123 | error_log logs/stream.log info; 124 | 125 | server { 126 | listen 7999; 127 | push_protocol; 128 | push_data_subprotocol 0; 129 | push_close_session_subprotocol 1; 130 | } 131 | server { 132 | listen 8000; 133 | lencontent_protocol; 134 | fake_http_subprotocol; 135 | http_proxy_pass 127.0.0.1:10000/$fhttp_api; 136 | http_proxy_last_uri /CloseSession; 137 | http_proxy_add_header PushUrl 127.0.0.1:7999/$sessiontoken; 138 | } 139 | server { 140 | listen 8001; 141 | websocket_protocol; 142 | fake_http_subprotocol; 143 | http_proxy_pass 127.0.0.1:10000/$fhttp_api; 144 | http_proxy_last_uri /CloseSession; 145 | http_proxy_add_header PushUrl 127.0.0.1:7999/$sessiontoken; 146 | } 147 | } 148 | 149 | -------------------------------------------------------------------------------- /push/php/CloseConnectionPusher.inc: -------------------------------------------------------------------------------- 1 | data_ = $data; 16 | } 17 | 18 | protected function subProtocolData(): string { 19 | // TODO: Implement subProtocolData() method. 20 | return $this->data_; 21 | } 22 | 23 | private $data_; 24 | } -------------------------------------------------------------------------------- /push/php/PushState.inc: -------------------------------------------------------------------------------- 1 | 15 | * sizeof(sequece) = 4. net order 16 | * sizeof(token) = 32 . hex 17 | * sizeof(subprotocol) = 1. 18 | * sizeof(len) = 4. len = sizof(data) net order 19 | * data: subprotocol request data 20 | * 21 | * response: 22 | * sequece | state | len | 23 | * sizeof(sequece) = 4. net order 24 | * sizeof(state) = 1. 25 | * state = 0: success; 1: hostname error 26 | * ; 2: token not exist; 3: server intelnal error 27 | * sizeof(len) = 4. len = sizeof(data) net order 28 | * data: subprotocol response data 29 | */ 30 | 31 | abstract class Pusher { 32 | 33 | function __construct(int $subProtocol) { 34 | $this->subProtocol_ = $subProtocol; 35 | } 36 | 37 | /** 38 | * @param string $sessionToken [host:port/sessiontoken] 39 | * @return int 40 | */ 41 | public function pushTo(string $url): int { 42 | $re = parse_url($url); 43 | if ($re === false || !$re["host"] || !$re["port"] || !$re["path"]) { 44 | return PushState::UrlError; 45 | } 46 | 47 | if (!$this->fd($re["host"], $re["port"])) { 48 | return PushState::HostConnectionError; 49 | } 50 | 51 | $sessionToken = substr($re["path"], 1); // trim the first '/' 52 | 53 | $seq = time(); 54 | $data = $this->subProtocolData(); 55 | 56 | $request = pack("N", $seq).$sessionToken.pack("C", $this->subProtocol_) 57 | .pack("N", strlen($data)).$data; 58 | 59 | $fd = $this->fd_; 60 | 61 | stream_set_timeout($fd, 5); 62 | if (!fwrite($fd, $request)) { 63 | return PushState::ElseError; 64 | } 65 | $status = stream_get_meta_data($this->fd_); 66 | if ($status['timed_out']) { 67 | return PushState::PushTimeout; 68 | } 69 | 70 | stream_set_timeout($fd, 5); 71 | $res = fread($fd, 9); 72 | if (!$res) { 73 | return PushState::ElseError; 74 | } 75 | $response = unpack("Nseq/Cst/Nlen", $res); 76 | $status = stream_get_meta_data($this->fd_); 77 | if ($status['timed_out']) { 78 | return PushState::PushTimeout; 79 | } 80 | 81 | if ($seq != $response["seq"]) { 82 | return PushState::PushServerError; 83 | } 84 | if ($response["len"] !== 0) { 85 | $this->result_ = fread($fd, $response["len"]); 86 | } 87 | 88 | return $response["st"]; 89 | } 90 | 91 | private function fd(string $host, int $port):bool { 92 | try { 93 | $this->fd_ = fsockopen($host, $port, $errNO, $errStr, 10); 94 | }catch (\Exception $e) { 95 | return false; 96 | } 97 | return true; 98 | } 99 | 100 | abstract protected function subProtocolData():string ; 101 | 102 | public function result():string { 103 | return $this->result_; 104 | } 105 | 106 | private $fd_; 107 | private $result_=""; 108 | private $subProtocol_; 109 | 110 | } -------------------------------------------------------------------------------- /push/php/testCloseConnectionPusher.php: -------------------------------------------------------------------------------- 1 | pushTo($argv[1])); 17 | echo "\n"; 18 | -------------------------------------------------------------------------------- /push/php/testDataPusher.php: -------------------------------------------------------------------------------- 1 | pushTo($argv[1])); 15 | echo "\n"; 16 | 17 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_core_module/config: -------------------------------------------------------------------------------- 1 | 2 | 3 | ngx_addon_name="ngx_stream_request_core_module" 4 | 5 | ngx_module_name="ngx_stream_request_core_module" 6 | ngx_module_srcs="$ngx_addon_dir/ngx_stream_request.c \ 7 | $ngx_addon_dir/ngx_stream_request_core_module.c \ 8 | $ngx_addon_dir/ngx_stream_request_script.c \ 9 | $ngx_addon_dir/ngx_stream_request_variables.c \ 10 | $ngx_addon_dir/ngx_stream_request_upstream.c \ 11 | $ngx_addon_dir/ngx_radix64_tree.c \ 12 | $ngx_addon_dir/ngx_str_str_rbtree.c" 13 | ngx_module_deps="$ngx_addon_dir/ngx_stream_request.h \ 14 | $ngx_addon_dir/ngx_stream_request_upstream.h \ 15 | $ngx_addon_dir/ngx_stream_request_variables.h \ 16 | $ngx_addon_dir/ngx_stream_request_script.h \ 17 | $ngx_addon_dir/ngx_radix64_tree.h \ 18 | $ngx_addon_dir/ngx_str_str_rbtree.h" 19 | ngx_module_type=STREAM 20 | ngx_module_incs=$ngx_addon_dir 21 | 22 | . auto/module 23 | 24 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_core_module/ngx_radix64_tree.c: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_radix64_tree.c 3 | // nginx-1.12 4 | // 5 | // Created by xpwu on 2017/12/24. 6 | // Copyright © 2017年 xpwu. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | static ngx_radix_node_t *ngx_radix_alloc(ngx_radix_tree_t *tree); 15 | 16 | 17 | ngx_int_t 18 | ngx_radix64tree_insert(ngx_radix_tree_t *tree, uint64_t key, uint64_t mask, 19 | uintptr_t value) 20 | { 21 | uint64_t bit; 22 | ngx_radix_node_t *node, *next; 23 | 24 | bit = 0x8000000000000000; 25 | 26 | node = tree->root; 27 | next = tree->root; 28 | 29 | while (bit & mask) { 30 | if (key & bit) { 31 | next = node->right; 32 | 33 | } else { 34 | next = node->left; 35 | } 36 | 37 | if (next == NULL) { 38 | break; 39 | } 40 | 41 | bit >>= 1; 42 | node = next; 43 | } 44 | 45 | if (next) { 46 | if (node->value != NGX_RADIX_NO_VALUE) { 47 | return NGX_BUSY; 48 | } 49 | 50 | node->value = value; 51 | return NGX_OK; 52 | } 53 | 54 | while (bit & mask) { 55 | next = ngx_radix_alloc(tree); 56 | if (next == NULL) { 57 | return NGX_ERROR; 58 | } 59 | 60 | next->right = NULL; 61 | next->left = NULL; 62 | next->parent = node; 63 | next->value = NGX_RADIX_NO_VALUE; 64 | 65 | if (key & bit) { 66 | node->right = next; 67 | 68 | } else { 69 | node->left = next; 70 | } 71 | 72 | bit >>= 1; 73 | node = next; 74 | } 75 | 76 | node->value = value; 77 | 78 | return NGX_OK; 79 | } 80 | 81 | 82 | ngx_int_t 83 | ngx_radix64tree_delete(ngx_radix_tree_t *tree, uint64_t key, uint64_t mask) 84 | { 85 | uint64_t bit; 86 | ngx_radix_node_t *node; 87 | 88 | bit = 0x8000000000000000; 89 | node = tree->root; 90 | 91 | while (node && (bit & mask)) { 92 | if (key & bit) { 93 | node = node->right; 94 | 95 | } else { 96 | node = node->left; 97 | } 98 | 99 | bit >>= 1; 100 | } 101 | 102 | if (node == NULL) { 103 | return NGX_ERROR; 104 | } 105 | 106 | if (node->right || node->left) { 107 | if (node->value != NGX_RADIX_NO_VALUE) { 108 | node->value = NGX_RADIX_NO_VALUE; 109 | return NGX_OK; 110 | } 111 | 112 | return NGX_ERROR; 113 | } 114 | 115 | for ( ;; ) { 116 | if (node->parent->right == node) { 117 | node->parent->right = NULL; 118 | 119 | } else { 120 | node->parent->left = NULL; 121 | } 122 | 123 | node->right = tree->free; 124 | tree->free = node; 125 | 126 | node = node->parent; 127 | 128 | if (node->right || node->left) { 129 | break; 130 | } 131 | 132 | if (node->value != NGX_RADIX_NO_VALUE) { 133 | break; 134 | } 135 | 136 | if (node->parent == NULL) { 137 | break; 138 | } 139 | } 140 | 141 | return NGX_OK; 142 | } 143 | 144 | 145 | uintptr_t 146 | ngx_radix64tree_find(ngx_radix_tree_t *tree, uint64_t key) 147 | { 148 | uint64_t bit; 149 | uintptr_t value; 150 | ngx_radix_node_t *node; 151 | 152 | bit = 0x8000000000000000; 153 | value = NGX_RADIX_NO_VALUE; 154 | node = tree->root; 155 | 156 | while (node) { 157 | if (node->value != NGX_RADIX_NO_VALUE) { 158 | value = node->value; 159 | } 160 | 161 | if (key & bit) { 162 | node = node->right; 163 | 164 | } else { 165 | node = node->left; 166 | } 167 | 168 | bit >>= 1; 169 | } 170 | 171 | return value; 172 | } 173 | 174 | static ngx_radix_node_t * 175 | ngx_radix_alloc(ngx_radix_tree_t *tree) 176 | { 177 | ngx_radix_node_t *p; 178 | 179 | if (tree->free) { 180 | p = tree->free; 181 | tree->free = tree->free->right; 182 | return p; 183 | } 184 | 185 | if (tree->size < sizeof(ngx_radix_node_t)) { 186 | tree->start = ngx_pmemalign(tree->pool, ngx_pagesize, ngx_pagesize); 187 | if (tree->start == NULL) { 188 | return NULL; 189 | } 190 | 191 | tree->size = ngx_pagesize; 192 | } 193 | 194 | p = (ngx_radix_node_t *) tree->start; 195 | tree->start += sizeof(ngx_radix_node_t); 196 | tree->size -= sizeof(ngx_radix_node_t); 197 | 198 | return p; 199 | } 200 | 201 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_core_module/ngx_radix64_tree.h: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_radix64_tree.h 3 | // nginx-1.12 4 | // 5 | // Created by xpwu on 2017/12/24. 6 | // Copyright © 2017年 xpwu. All rights reserved. 7 | // 8 | 9 | #ifndef ngx_radix64_tree_h 10 | #define ngx_radix64_tree_h 11 | 12 | #include 13 | #include 14 | 15 | ngx_int_t ngx_radix64tree_insert(ngx_radix_tree_t *tree, 16 | uint64_t key, uint64_t mask, uintptr_t value); 17 | ngx_int_t ngx_radix64tree_delete(ngx_radix_tree_t *tree, 18 | uint64_t key, uint64_t mask); 19 | uintptr_t ngx_radix64tree_find(ngx_radix_tree_t *tree, uint64_t key); 20 | 21 | 22 | #endif /* ngx_radix64_tree_h */ 23 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_core_module/ngx_str_str_rbtree.c: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_str_str_rbtree.c 3 | // ngx-1.10.1-xcode 4 | // 5 | // Created by xpwu on 2016/11/18. 6 | // Copyright © 2016年 xpwu. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #ifndef ngx_str_str_rbtree_c 12 | #define ngx_str_str_rbtree_c 13 | 14 | typedef struct{ 15 | ngx_str_node_t node; // must be first, not be pointer 16 | ngx_str_t value; 17 | } ngx_str_str_rbtree_node_t; 18 | 19 | extern void ngx_str_str_rbtree_init(ngx_str_str_rbtree* tree 20 | , ngx_pool_t* pool, ngx_log_t* log) { 21 | ngx_rbtree_init(&tree->tree, &tree->sentinel 22 | , ngx_str_rbtree_insert_value); 23 | tree->pool = pool; 24 | tree->log = log; 25 | } 26 | 27 | #if (NGX_DEBUG) 28 | static void print_rbtree(ngx_rbtree_node_t* root 29 | , ngx_rbtree_node_t* sentinel 30 | , u_char** buf, u_char* last, ngx_int_t* end) { 31 | if (root == sentinel) { 32 | return; 33 | } 34 | 35 | if (*end == 1) { 36 | return; 37 | } 38 | 39 | print_rbtree(root->left, sentinel, buf, last, end); 40 | 41 | ngx_str_str_rbtree_node_t* node = (ngx_str_str_rbtree_node_t*)root; 42 | if (*buf + node->node.str.len + node->value.len + 4 > last) { 43 | *buf = ngx_cpymem(*buf, ";...", 4); 44 | *end = 1; 45 | } else { 46 | *buf = ngx_cpymem(*buf, node->node.str.data, node->node.str.len); 47 | *buf = ngx_cpymem(*buf, ": ", 2); 48 | *buf = ngx_cpymem(*buf, node->value.data, node->value.len); 49 | *buf = ngx_cpymem(*buf, "; ", 2); 50 | } 51 | 52 | print_rbtree(root->right, sentinel, buf, last, end); 53 | } 54 | #endif 55 | 56 | extern ngx_str_t ngx_str_str_rbtree_get_value(ngx_str_str_rbtree* tree 57 | , ngx_str_t key) { 58 | #if (NGX_DEBUG) 59 | ngx_log_t* log = tree->log; 60 | u_char allVar[1024]; 61 | u_char* last = allVar + 1024; 62 | u_char* buf = allVar; 63 | ngx_int_t end = 0; 64 | print_rbtree(tree->tree.root, tree->tree.sentinel, &buf, last, &end); 65 | ngx_log_debug3(NGX_LOG_DEBUG_STREAM, log, 0 66 | , "ngx str_str_rbtree<%p> all variable is {%*s}" 67 | , tree, buf-allVar, allVar); 68 | #endif 69 | 70 | ngx_str_t res = ngx_null_string; 71 | 72 | ngx_str_node_t* node = ngx_str_rbtree_lookup(&tree->tree, &key, 0); 73 | if (node == NULL) { 74 | ngx_log_debug2(NGX_LOG_DEBUG_STREAM, tree->log, 0 75 | , "ngx str_str_rbtree<%p> get key(%V) is null" 76 | , tree, &key); 77 | return res; 78 | } 79 | 80 | ngx_str_str_rbtree_node_t* vnode = (ngx_str_str_rbtree_node_t*)node; 81 | ngx_log_debug3(NGX_LOG_DEBUG_STREAM, tree->log, 0 82 | , "ngx str_str_rbtree<%p> get key(%V) is (%V)" 83 | , tree, &key, &vnode->value); 84 | return vnode->value; 85 | } 86 | 87 | extern void ngx_str_str_rbtree_set_value(ngx_str_str_rbtree* tree 88 | , ngx_str_t key 89 | , ngx_str_t value 90 | , ngx_int_t force_rewrite) { 91 | ngx_str_str_rbtree_node_t* vnode; 92 | 93 | ngx_str_node_t* node = ngx_str_rbtree_lookup(&tree->tree, &key, 0); 94 | 95 | if (node != NULL && force_rewrite == 0) { 96 | #if (NGX_DEBUG) 97 | ngx_str_str_rbtree_node_t* vnode = (ngx_str_str_rbtree_node_t*)node; 98 | ngx_log_debug3(NGX_LOG_DEBUG_STREAM, tree->log, 0 99 | , "ngx str_str_rbtree<%p> key(%V) has value (%V) yet" 100 | ,tree, &key, &vnode->value); 101 | #endif 102 | return; 103 | } 104 | 105 | if (node != NULL) { 106 | vnode = (ngx_str_str_rbtree_node_t*)node; 107 | if (vnode->value.len >= value.len) { 108 | ngx_memcpy(vnode->value.data, value.data, value.len); 109 | } else { 110 | ngx_pfree(tree->pool, vnode->value.data); 111 | vnode->value.data = ngx_pcalloc(tree->pool, value.len); 112 | ngx_memcpy(vnode->value.data, value.data, value.len); 113 | } 114 | vnode->value.len = value.len; 115 | return; 116 | } 117 | 118 | vnode = ngx_pcalloc(tree->pool, sizeof(ngx_str_str_rbtree_node_t)); 119 | /** 120 | * set by ngx_pcalloc: 121 | * vnode->node.node.key = 0; 122 | */ 123 | vnode->value.data = ngx_pcalloc(tree->pool, value.len); 124 | ngx_memcpy(vnode->value.data, value.data, value.len); 125 | vnode->value.len = value.len; 126 | 127 | vnode->node.str.len = key.len; 128 | vnode->node.str.data = ngx_pcalloc(tree->pool, key.len); 129 | ngx_memcpy(vnode->node.str.data, key.data, key.len); 130 | 131 | ngx_rbtree_insert(&tree->tree, (ngx_rbtree_node_t*)vnode); 132 | } 133 | 134 | #endif //~ngx_str_str_rbtree_c 135 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_core_module/ngx_str_str_rbtree.h: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_str_str_rbtree.h 3 | // ngx-1.10.1-xcode 4 | // 5 | // Created by xpwu on 2016/11/18. 6 | // Copyright © 2016年 xpwu. All rights reserved. 7 | // 8 | 9 | #ifndef ngx_str_str_rbtree_h 10 | #define ngx_str_str_rbtree_h 11 | 12 | #include 13 | #include 14 | 15 | typedef struct{ 16 | ngx_rbtree_t tree; 17 | ngx_rbtree_node_t sentinel; 18 | ngx_pool_t* pool; 19 | ngx_log_t* log; 20 | } ngx_str_str_rbtree; 21 | 22 | extern void ngx_str_str_rbtree_init(ngx_str_str_rbtree* tree 23 | , ngx_pool_t* pool, ngx_log_t* log); 24 | 25 | extern ngx_str_t ngx_str_str_rbtree_get_value(ngx_str_str_rbtree* tree 26 | , ngx_str_t key); 27 | extern void ngx_str_str_rbtree_set_value(ngx_str_str_rbtree* tree 28 | , ngx_str_t key 29 | , ngx_str_t value 30 | , ngx_int_t force_rewrite); 31 | 32 | #define ngx_str_str_rbtree_is_empty(rbtree_ptr) \ 33 | ((tree_ptr)->tree->root == (tree_ptr)->tree->sentinel ? 1 : 0); 34 | 35 | #endif /* ngx_str_str_rbtree_h */ 36 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_core_module/ngx_stream_request.c: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_stream_request.c 3 | // nginx-1.12 4 | // 5 | // Created by xpwu on 2017/12/16. 6 | // Copyright © 2017年 xpwu. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | extern void ngx_stream_request_regular_data(ngx_stream_request_t* r) { 12 | if (r->data == NULL) { 13 | return; 14 | } 15 | ngx_chain_t* chain = NULL, *prev=NULL; 16 | for (chain = r->data->next, prev = r->data 17 | ; chain != NULL; chain=chain->next) { 18 | if (ngx_buf_size(chain->buf) == 0) { 19 | prev->next = chain->next; 20 | } else { 21 | prev = chain; 22 | } 23 | } 24 | if (ngx_buf_size(r->data->buf) == 0) { 25 | r->data = r->data->next; 26 | } 27 | } 28 | 29 | extern void ngx_stream_request_set_data(ngx_stream_request_t* r, char* err_info) { 30 | ngx_int_t len = ngx_strlen(err_info); 31 | 32 | r->data->buf = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); 33 | r->data->buf = ngx_create_temp_buf(r->pool, len); 34 | r->data->next = NULL; 35 | ngx_memcpy(r->data->buf->last, err_info, len); 36 | r->data->buf->last += len; 37 | } 38 | 39 | extern ngx_uint_t ngx_chain_len(ngx_chain_t* chain) { 40 | ngx_uint_t len = 0; 41 | for (; chain != NULL; chain = chain->next) { 42 | len += chain->buf->last - chain->buf->pos; 43 | } 44 | return len; 45 | } 46 | 47 | extern void ngx_regular_buf(ngx_buf_t* buf) { 48 | off_t size = ngx_buf_size(buf); 49 | if (size != 0) { 50 | ngx_memmove(buf->start, buf->pos, size); 51 | } 52 | buf->pos = buf->start; 53 | buf->last = buf->pos + size; 54 | } 55 | 56 | static ngx_int_t is_equal_str(ngx_str_t* str1, ngx_str_t* str2) { 57 | if (str1->len != str2->len) { 58 | return 0; 59 | } 60 | if (0 != ngx_strncmp(str1->data, str2->data, str2->len)) { 61 | return 0; 62 | } 63 | return 1; 64 | } 65 | 66 | extern ngx_array_t* ngx_merge_key_val_array(ngx_pool_t* pool, ngx_array_t* parent 67 | , ngx_array_t* child) { 68 | 69 | if (parent == NULL && child == NULL) { 70 | return NULL; 71 | } 72 | ngx_int_t len = 0; 73 | if (parent != NULL) { 74 | len += parent->nelts; 75 | } 76 | if (child != NULL) { 77 | len += child->nelts; 78 | } 79 | ngx_array_t* re = ngx_array_create(pool, len 80 | , sizeof(ngx_keyval_t)); 81 | 82 | ngx_array_t* arrs[2]; 83 | arrs[0] = parent; 84 | arrs[1] = child; 85 | 86 | ngx_int_t i = 0; 87 | for (i = 1; i >= 0; --i) { 88 | if (arrs[i] == NULL) { 89 | continue; 90 | } 91 | 92 | ngx_keyval_t* elts = arrs[i]->elts; 93 | ngx_uint_t j = arrs[i]->nelts; 94 | for (; j > 0; --j) { 95 | int contin = 0; 96 | 97 | ngx_uint_t k = 0; 98 | ngx_keyval_t* res = re->elts; 99 | for (; k < re->nelts; ++k) { 100 | if (1 == is_equal_str(&res[k].key, &elts[j-1].key)) { 101 | contin = 1; 102 | break; 103 | } 104 | } 105 | if (contin) { 106 | continue; 107 | } 108 | res = ngx_array_push(re); 109 | res->key = elts[j-1].key; 110 | res->value = elts[j-1].value; 111 | } 112 | } 113 | 114 | return re; 115 | } 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_core_module/ngx_stream_request.h: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_stream_request.h 3 | // nginx-1.12 4 | // 5 | // Created by xpwu on 2017/12/16. 6 | // Copyright © 2017年 xpwu. All rights reserved. 7 | // 8 | 9 | #ifndef ngx_stream_request_h 10 | #define ngx_stream_request_h 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #define NGX_HANDLER_STOP NGX_DECLINED 20 | 21 | typedef struct ngx_stream_request_s ngx_stream_request_t; 22 | typedef struct ngx_stream_request_upstream_s ngx_stream_request_upstream_t; 23 | typedef struct ngx_stream_request_core_srv_conf_s ngx_stream_request_core_srv_conf_t; 24 | typedef struct ngx_stream_request_handler_s ngx_stream_request_handler_t; 25 | typedef struct ngx_stream_request_protocol_s ngx_stream_request_protocol_t; 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | typedef struct ngx_stream_request_cleanup_s ngx_stream_request_cleanup_t; 32 | typedef struct ngx_stream_cleanup_s ngx_stream_cleanup_t; 33 | typedef void (*ngx_stream_cleanup_pt)(void *data); 34 | typedef void (*ngx_stream_request_cleanup_pt)(void *data); 35 | 36 | #define NGX_STREAM_REQUEST_ERROR (ngx_stream_request_t*)NGX_ERROR 37 | #define NGX_STREAM_REQUEST_AGAIN (ngx_stream_request_t*)NULL 38 | 39 | #define ngx_stream_request_get_module_ctx(r, module) (r)->ctx[module.ctx_index] 40 | #define ngx_stream_request_set_ctx(r, c, module) r->ctx[module.ctx_index] = c; 41 | #define ngx_stream_request_delete_ctx(r, module) r->ctx[module.ctx_index] = NULL; 42 | 43 | extern void ngx_stream_finalize_session_r(ngx_stream_session_t *s, char* reason); 44 | extern void ngx_stream_finalize_session_r_level(ngx_stream_session_t *s 45 | , char* reason 46 | , ngx_uint_t level); 47 | extern ngx_stream_request_t* ngx_stream_new_request(ngx_stream_session_t*); 48 | /* run loop */ 49 | extern void ngx_stream_handle_request(ngx_stream_request_t*); 50 | // 从index个的response方向开始处理request. response: 1/0 51 | // index < 0 表示从后向前的index. -1: 最后一个 52 | extern void ngx_stream_handle_request_from(ngx_stream_request_t* 53 | , ngx_int_t index, ngx_int_t response); 54 | 55 | extern ngx_stream_request_handler_t* ngx_stream_request_add_handler(ngx_conf_t*); 56 | 57 | extern void ngx_stream_request_regular_data(ngx_stream_request_t*); 58 | extern void ngx_stream_request_set_data(ngx_stream_request_t*, char* err_info); 59 | 60 | extern ngx_stream_cleanup_t * ngx_stream_cleanup_add(ngx_stream_session_t *s); 61 | extern ngx_stream_request_cleanup_t * 62 | ngx_stream_request_cleanup_add(ngx_stream_request_t*); 63 | 64 | extern ngx_module_t ngx_stream_request_core_module; 65 | /* protolcol must set this function to ngx_stream_core_srv_conf_t->handler */ 66 | extern void ngx_stream_request_core_handler(ngx_stream_session_t *s); 67 | 68 | extern void ngx_regular_buf(ngx_buf_t* buf); 69 | extern ngx_uint_t ngx_chain_len(ngx_chain_t* chain); 70 | extern ngx_array_t* ngx_merge_key_val_array(ngx_pool_t* pool, ngx_array_t* parent 71 | , ngx_array_t* child); 72 | 73 | #define NGX_STREAM_REQUEST_SUBPROTOCOL_ANY -1 74 | 75 | struct ngx_stream_request_s{ 76 | ngx_stream_session_t* session; 77 | ngx_stream_request_upstream_t* upstream; 78 | 79 | ngx_pool_t* pool; 80 | 81 | // NGX_STREAM_REQUEST_SUBPROTOCOL_ANY: 表示不关注具体的子协议 82 | ngx_int_t subprotocol_flag; 83 | 84 | ngx_chain_t* data; // in / out 85 | ngx_int_t error; // 标示data中的数据 86 | 87 | void** ctx; 88 | 89 | ngx_stream_request_variable_value_t *variables; 90 | #if (NGX_PCRE) 91 | ngx_uint_t ncaptures; 92 | int *captures; 93 | u_char *captures_data; 94 | #endif 95 | 96 | ngx_stream_request_cleanup_t* cln; 97 | 98 | char* close_reason; // 当数据发送结束时,是否关闭连接,和关闭原因 99 | 100 | ngx_queue_t list; 101 | } ; 102 | 103 | struct ngx_stream_cleanup_s { 104 | ngx_stream_cleanup_pt handler; 105 | void *data; 106 | ngx_stream_cleanup_t *next; 107 | }; 108 | 109 | struct ngx_stream_request_cleanup_s { 110 | ngx_stream_request_cleanup_pt handler; 111 | void *data; 112 | ngx_stream_request_cleanup_t *next; 113 | }; 114 | 115 | typedef struct { 116 | ngx_hash_t variables_hash; 117 | 118 | ngx_array_t variables; /* ngx_stream_variable_t */ 119 | ngx_array_t prefix_variables; /* ngx_stream_variable_t */ 120 | ngx_uint_t ncaptures; 121 | 122 | ngx_uint_t variables_hash_max_size; 123 | ngx_uint_t variables_hash_bucket_size; 124 | 125 | ngx_hash_keys_arrays_t *variables_keys; 126 | 127 | } ngx_stream_request_core_main_conf_t; 128 | 129 | struct ngx_stream_request_handler_s{ 130 | // NGX_STREAM_REQUEST_SUBPROTOCOL_ANY: 表示不关注具体的子协议 131 | ngx_int_t subprotocol_flag; 132 | ngx_int_t index; // set by ngx_stream_request_add_handler 133 | char* name; 134 | /* NGX_OK; NGX_AGAIN; NGX_ERROR; NGX_HANDLER_STOP */ 135 | ngx_int_t (*handle_request)(ngx_stream_request_t*); 136 | ngx_int_t (*build_response)(ngx_stream_request_t*); 137 | }; 138 | 139 | struct ngx_stream_request_protocol_s { 140 | void (*init_parser)(ngx_stream_session_t*); 141 | ngx_stream_request_t* (*get_request)(ngx_stream_session_t*); 142 | 143 | ngx_stream_request_handler_t handler; 144 | }; 145 | 146 | struct ngx_stream_request_core_srv_conf_s{ 147 | // client 148 | ngx_msec_t heartbeat; 149 | ngx_msec_t receive_from_client_timeout; 150 | ngx_msec_t send_to_client_timeout; 151 | 152 | // upstream 153 | ngx_msec_t send_to_proxy_timeout; 154 | ngx_msec_t receive_from_proxy_timeout; 155 | ngx_msec_t proxy_response_timeout; 156 | ngx_msec_t next_upstream_timeout; //查找next upstream 的最长时间 157 | ngx_uint_t next_upstream_tries; //next upstream 的最大重试次数 158 | ngx_flag_t next_upstream; //是否自动寻找下一个 159 | ngx_msec_t connect_timeout; // connect upstream 的超时时间 160 | 161 | ngx_addr_t *local; 162 | 163 | ngx_stream_upstream_srv_conf_t* upstream; 164 | 165 | ngx_stream_request_protocol_t protocol; 166 | 167 | ngx_array_t handlers; /* ngx_stream_request_handler_t */ 168 | }; 169 | 170 | 171 | #endif /* ngx_stream_request_h */ 172 | 173 | 174 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_core_module/ngx_stream_request_script.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Igor Sysoev 4 | * Copyright (C) Nginx, Inc. 5 | */ 6 | 7 | 8 | #ifndef _NGX_STREAM_REQUEST_SCRIPT_H_INCLUDED_ 9 | #define _NGX_STREAM_REQUEST_SCRIPT_H_INCLUDED_ 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | typedef struct { 18 | u_char *ip; 19 | u_char *pos; 20 | ngx_stream_request_variable_value_t *sp; 21 | 22 | ngx_str_t buf; 23 | ngx_str_t line; 24 | 25 | unsigned flushed:1; 26 | unsigned skip:1; 27 | 28 | ngx_stream_request_t *request; 29 | } ngx_stream_request_script_engine_t; 30 | 31 | 32 | //typedef struct { 33 | // ngx_conf_t *cf; 34 | // ngx_str_t *source; 35 | // 36 | // ngx_array_t **flushes; 37 | // ngx_array_t **lengths; 38 | // ngx_array_t **values; 39 | // 40 | // ngx_uint_t variables; 41 | // ngx_uint_t ncaptures; 42 | // ngx_uint_t size; 43 | // 44 | // void *main; 45 | // 46 | // unsigned complete_lengths:1; 47 | // unsigned complete_values:1; 48 | // unsigned zero:1; 49 | // unsigned conf_prefix:1; 50 | // unsigned root_prefix:1; 51 | //} ngx_stream_script_compile_t; 52 | 53 | typedef ngx_stream_script_compile_t ngx_stream_request_script_compile_t; 54 | 55 | 56 | //typedef struct { 57 | // ngx_str_t value; 58 | // ngx_uint_t *flushes; 59 | // void *lengths; 60 | // void *values; 61 | //} ngx_stream_complex_value_t; 62 | 63 | typedef ngx_stream_complex_value_t ngx_stream_request_complex_value_t; 64 | 65 | 66 | typedef struct { 67 | ngx_conf_t *cf; 68 | ngx_str_t *value; 69 | ngx_stream_request_complex_value_t *complex_value; 70 | 71 | unsigned zero:1; 72 | unsigned conf_prefix:1; 73 | unsigned root_prefix:1; 74 | } ngx_stream_request_compile_complex_value_t; 75 | 76 | 77 | typedef void (*ngx_stream_request_script_code_pt) 78 | (ngx_stream_request_script_engine_t *e); 79 | typedef size_t (*ngx_stream_request_script_len_code_pt) (ngx_stream_request_script_engine_t *e); 80 | 81 | 82 | typedef struct { 83 | ngx_stream_request_script_code_pt code; 84 | uintptr_t len; 85 | } ngx_stream_request_script_copy_code_t; 86 | 87 | 88 | typedef struct { 89 | ngx_stream_request_script_code_pt code; 90 | uintptr_t index; 91 | } ngx_stream_request_script_var_code_t; 92 | 93 | 94 | typedef struct { 95 | ngx_stream_request_script_code_pt code; 96 | uintptr_t n; 97 | } ngx_stream_request_script_copy_capture_code_t; 98 | 99 | 100 | typedef struct { 101 | ngx_stream_request_script_code_pt code; 102 | uintptr_t conf_prefix; 103 | } ngx_stream_request_script_full_name_code_t; 104 | 105 | 106 | void ngx_stream_request_script_flush_complex_value(ngx_stream_request_t *r, 107 | ngx_stream_request_complex_value_t *val); 108 | ngx_int_t ngx_stream_request_complex_value(ngx_stream_request_t *r, 109 | ngx_stream_request_complex_value_t *val, ngx_str_t *value); 110 | ngx_int_t ngx_stream_request_compile_complex_value( 111 | ngx_stream_request_compile_complex_value_t *ccv); 112 | char *ngx_stream_request_set_complex_value_slot(ngx_conf_t *cf 113 | , ngx_command_t *cmd, 114 | void *conf); 115 | 116 | 117 | ngx_uint_t ngx_stream_request_script_variables_count(ngx_str_t *value); 118 | ngx_int_t ngx_stream_request_script_compile( 119 | ngx_stream_request_script_compile_t *sc); 120 | u_char *ngx_stream_request_script_run(ngx_stream_request_t *r 121 | , ngx_str_t *value, 122 | void *code_lengths, size_t reserved, void *code_values); 123 | void ngx_stream_request_script_flush_no_cacheable_variables( 124 | ngx_stream_request_t *r, 125 | ngx_array_t *indices); 126 | 127 | void *ngx_stream_request_script_add_code(ngx_array_t *codes, size_t size, void *code); 128 | 129 | size_t ngx_stream_request_script_copy_len_code(ngx_stream_request_script_engine_t *e); 130 | void ngx_stream_request_script_copy_code(ngx_stream_request_script_engine_t *e); 131 | size_t ngx_stream_request_script_copy_var_len_code(ngx_stream_request_script_engine_t *e); 132 | void ngx_stream_request_script_copy_var_code(ngx_stream_request_script_engine_t *e); 133 | size_t ngx_stream_request_script_copy_capture_len_code(ngx_stream_request_script_engine_t *e); 134 | void ngx_stream_request_script_copy_capture_code(ngx_stream_request_script_engine_t *e); 135 | 136 | #endif /* _NGX_STREAM_SCRIPT_H_INCLUDED_ */ 137 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_core_module/ngx_stream_request_upstream.c: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_stream_request_upstream.c 3 | // nginx-1.12 4 | // 5 | // Created by xpwu on 2017/12/16. 6 | // Copyright © 2017年 xpwu. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | static void ngx_stream_request_proxy_connect_handler(ngx_event_t *ev); 14 | static ngx_int_t ngx_stream_request_core_test_connect(ngx_connection_t *c); 15 | static void ngx_stream_request_core_next_upstream(ngx_stream_request_t *r); 16 | static void ngx_stream_proxy_init_upstream(ngx_stream_request_t *r); 17 | 18 | static void empty_handler(ngx_event_t *ev){} 19 | 20 | static ngx_int_t 21 | ngx_stream_request_core_test_connect(ngx_connection_t *c) 22 | { 23 | int err; 24 | socklen_t len; 25 | 26 | #if (NGX_HAVE_KQUEUE) 27 | 28 | if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { 29 | err = c->write->kq_errno ? c->write->kq_errno : c->read->kq_errno; 30 | 31 | if (err) { 32 | (void) ngx_connection_error(c, err, 33 | "kevent() reported that connect() failed"); 34 | return NGX_ERROR; 35 | } 36 | 37 | } else 38 | #endif 39 | { 40 | err = 0; 41 | len = sizeof(int); 42 | 43 | /* 44 | * BSDs and Linux return 0 and set a pending error in err 45 | * Solaris returns -1 and sets errno 46 | */ 47 | 48 | if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) 49 | == -1) 50 | { 51 | err = ngx_socket_errno; 52 | } 53 | 54 | if (err) { 55 | (void) ngx_connection_error(c, err, "connect() failed"); 56 | return NGX_ERROR; 57 | } 58 | } 59 | 60 | return NGX_OK; 61 | } 62 | 63 | static void 64 | ngx_stream_request_core_next_upstream(ngx_stream_request_t *r) 65 | { 66 | ngx_msec_t timeout; 67 | ngx_connection_t *pc; 68 | ngx_stream_upstream_t *u; 69 | ngx_stream_request_core_srv_conf_t *pscf; 70 | 71 | ngx_log_debug0(NGX_LOG_DEBUG_STREAM, r->session->connection->log, 0, 72 | "stream proxy next upstream"); 73 | 74 | u = &r->upstream->upstream; 75 | 76 | if (u->peer.sockaddr) { 77 | u->peer.free(&u->peer, u->peer.data, NGX_PEER_FAILED); 78 | u->peer.sockaddr = NULL; 79 | } 80 | 81 | pscf = ngx_stream_get_module_srv_conf(r->session, ngx_stream_request_core_module); 82 | 83 | timeout = pscf->next_upstream_timeout; 84 | 85 | if (u->peer.tries == 0 86 | || !pscf->next_upstream 87 | || (timeout && ngx_current_msec - u->peer.start_time >= timeout)) 88 | { 89 | r->upstream->upstream_connect_failed(r, "has not upstream"); 90 | return; 91 | } 92 | 93 | pc = u->peer.connection; 94 | 95 | if (pc) { 96 | ngx_log_debug1(NGX_LOG_DEBUG_STREAM, r->session->connection->log, 0, 97 | "close proxy upstream connection: %d", pc->fd); 98 | 99 | ngx_close_connection(pc); 100 | u->peer.connection = NULL; 101 | } 102 | 103 | ngx_stream_request_upstream_connect(r); 104 | } 105 | 106 | void 107 | ngx_stream_request_upstream_connect(ngx_stream_request_t *r) 108 | { 109 | ngx_int_t rc; 110 | ngx_connection_t *c, *pc; 111 | ngx_stream_upstream_t *u; 112 | ngx_stream_request_core_srv_conf_t *pscf; 113 | ngx_stream_session_t* s; 114 | 115 | s = r->session; 116 | c = s->connection; 117 | 118 | // c->log->action = ""; 119 | 120 | u = &r->upstream->upstream; 121 | 122 | rc = ngx_event_connect_peer(&u->peer); 123 | 124 | 125 | #ifdef NGX_DEBUG 126 | char* rc_s = ""; 127 | switch (rc) { 128 | case -1: 129 | rc_s = "NGX_ERROR"; 130 | break; 131 | case -2: 132 | rc_s = "NGX_AGAIN"; 133 | break; 134 | case -3: 135 | rc_s = "NGX_BUSY"; 136 | break; 137 | default: 138 | rc_s = "-4: NGX_DONE; -5:NGX_DECLINED; -6:NGX_ABORT"; 139 | break; 140 | } 141 | #endif 142 | 143 | ngx_log_debug2(NGX_LOG_DEBUG_STREAM, c->log, 0 144 | , "proxy connect: %i, %s", rc, rc_s); 145 | 146 | if (rc == NGX_ERROR) { 147 | r->upstream->upstream_connect_failed(r, "connect upsteam peer error"); 148 | return; 149 | } 150 | 151 | if (rc == NGX_BUSY) { 152 | r->upstream->upstream_connect_failed(r, "no live upstreams"); 153 | return; 154 | } 155 | 156 | if (rc == NGX_DECLINED) { 157 | ngx_stream_request_core_next_upstream(r); 158 | return; 159 | } 160 | 161 | /* rc == NGX_OK || rc == NGX_AGAIN || rc == NGX_DONE */ 162 | 163 | pc = u->peer.connection; 164 | 165 | pc->data = r; 166 | pc->log = c->log; 167 | pc->pool = r->pool; 168 | pc->read->log = c->log; 169 | pc->write->log = c->log; 170 | 171 | if (rc != NGX_AGAIN) { 172 | ngx_stream_proxy_init_upstream(r); 173 | return; 174 | } 175 | 176 | pc->read->handler = ngx_stream_request_proxy_connect_handler; 177 | pc->write->handler = ngx_stream_request_proxy_connect_handler; 178 | 179 | pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_request_core_module); 180 | 181 | ngx_add_timer(pc->write, pscf->connect_timeout); 182 | } 183 | 184 | static void 185 | ngx_stream_proxy_init_upstream(ngx_stream_request_t *r) 186 | { 187 | int tcp_nodelay; 188 | // u_char *p; 189 | ngx_connection_t *c, *pc; 190 | ngx_log_handler_pt handler; 191 | ngx_stream_upstream_t *u; 192 | ngx_stream_core_srv_conf_t *cscf; 193 | ngx_stream_session_t* s = r->session; 194 | 195 | u = &r->upstream->upstream; 196 | pc = u->peer.connection; 197 | 198 | cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module); 199 | 200 | if (pc->type == SOCK_STREAM 201 | && cscf->tcp_nodelay 202 | && pc->tcp_nodelay == NGX_TCP_NODELAY_UNSET) 203 | { 204 | ngx_log_debug0(NGX_LOG_DEBUG_STREAM, pc->log, 0, "tcp_nodelay"); 205 | 206 | tcp_nodelay = 1; 207 | 208 | if (setsockopt(pc->fd, IPPROTO_TCP, TCP_NODELAY, 209 | (const void *) &tcp_nodelay, sizeof(int)) == -1) 210 | { 211 | ngx_connection_error(pc, ngx_socket_errno, 212 | "setsockopt(TCP_NODELAY) failed"); 213 | ngx_stream_request_core_next_upstream(r); 214 | return; 215 | } 216 | 217 | pc->tcp_nodelay = NGX_TCP_NODELAY_SET; 218 | } 219 | 220 | c = s->connection; 221 | 222 | if (c->log->log_level >= NGX_LOG_INFO) { 223 | ngx_str_t str; 224 | u_char addr[NGX_SOCKADDR_STRLEN]; 225 | 226 | str.len = NGX_SOCKADDR_STRLEN; 227 | str.data = addr; 228 | 229 | if (ngx_connection_local_sockaddr(pc, &str, 1) == NGX_OK) { 230 | handler = c->log->handler; 231 | c->log->handler = NULL; 232 | 233 | ngx_log_error(NGX_LOG_INFO, c->log, 0, 234 | "%sproxy %V connected to %V", 235 | pc->type == SOCK_DGRAM ? "udp " : "", 236 | &str, u->peer.name); 237 | 238 | c->log->handler = handler; 239 | } 240 | } 241 | 242 | u->connected = 1; 243 | 244 | pc->read->handler = empty_handler; 245 | pc->write->handler = empty_handler; 246 | 247 | r->upstream->upstream_connected(r); 248 | } 249 | 250 | static void 251 | ngx_stream_request_proxy_connect_handler(ngx_event_t *ev) 252 | { 253 | ngx_connection_t *c; 254 | // ngx_stream_session_t *s; 255 | ngx_stream_request_t* r; 256 | 257 | c = ev->data; 258 | r = c->data; 259 | // s = r->session; 260 | 261 | if (ev->timedout) { 262 | ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, "upstream timed out"); 263 | ngx_stream_request_core_next_upstream(r); 264 | return; 265 | } 266 | 267 | if (ev->timer_set) { 268 | ngx_del_timer(ev); 269 | } 270 | 271 | ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, 272 | "stream proxy connect upstream"); 273 | 274 | if (ngx_stream_request_core_test_connect(c) != NGX_OK) { 275 | ngx_stream_request_core_next_upstream(r); 276 | return; 277 | } 278 | 279 | ngx_stream_proxy_init_upstream(r); 280 | } 281 | 282 | 283 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_core_module/ngx_stream_request_upstream.h: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_stream_request_upstream.h 3 | // nginx-1.12 4 | // 5 | // Created by xpwu on 2017/12/16. 6 | // Copyright © 2017年 xpwu. All rights reserved. 7 | // 8 | 9 | #ifndef ngx_stream_request_upstream_h 10 | #define ngx_stream_request_upstream_h 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | struct ngx_stream_request_upstream_s{ 17 | ngx_stream_upstream_t upstream; 18 | void (*upstream_connected)(ngx_stream_request_t*); 19 | void (*upstream_connect_failed)(ngx_stream_request_t*, char* reason); 20 | } ; 21 | 22 | extern void ngx_stream_request_upstream_connect(ngx_stream_request_t *r); 23 | 24 | 25 | #endif /* ngx_stream_request_upstream_h */ 26 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_core_module/ngx_stream_request_variables.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Igor Sysoev 4 | * Copyright (C) Nginx, Inc. 5 | */ 6 | 7 | 8 | #ifndef _NGX_STREAM_REQUEST_VARIABLES_H_INCLUDED_ 9 | #define _NGX_STREAM_REQUEST_VARIABLES_H_INCLUDED_ 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | typedef ngx_variable_value_t ngx_stream_request_variable_value_t; 18 | 19 | #define ngx_stream_request_variable(v) { sizeof(v) - 1, 1, 0, 0, 0, (u_char *) v } 20 | 21 | typedef struct ngx_stream_request_variable_s ngx_stream_request_variable_t; 22 | 23 | typedef void (*ngx_stream_request_set_variable_pt) (ngx_stream_request_t *r, 24 | ngx_stream_request_variable_value_t *v, uintptr_t data); 25 | typedef ngx_int_t (*ngx_stream_request_get_variable_pt) (ngx_stream_request_t *r, 26 | ngx_stream_request_variable_value_t *v, uintptr_t data); 27 | 28 | 29 | #define NGX_STREAM_REQUEST_VAR_CHANGEABLE NGX_STREAM_VAR_CHANGEABLE 30 | #define NGX_STREAM_REQUEST_VAR_NOCACHEABLE NGX_STREAM_VAR_NOCACHEABLE 31 | #define NGX_STREAM_REQUEST_VAR_INDEXED NGX_STREAM_VAR_INDEXED 32 | #define NGX_STREAM_REQUEST_VAR_NOHASH NGX_STREAM_VAR_NOHASH 33 | #define NGX_STREAM_REQUEST_VAR_WEAK NGX_STREAM_VAR_WEAK 34 | #define NGX_STREAM_REQUEST_VAR_PREFIX NGX_STREAM_VAR_PREFIX 35 | 36 | 37 | struct ngx_stream_request_variable_s { 38 | ngx_str_t name; /* must be first to build the hash */ 39 | ngx_stream_request_set_variable_pt set_handler; 40 | ngx_stream_request_get_variable_pt get_handler; 41 | uintptr_t data; 42 | ngx_uint_t flags; 43 | ngx_uint_t index; 44 | }; 45 | 46 | 47 | ngx_stream_request_variable_t *ngx_stream_request_add_variable(ngx_conf_t *cf 48 | , ngx_str_t *name, ngx_uint_t flags); 49 | ngx_int_t ngx_stream_request_get_variable_index(ngx_conf_t *cf, ngx_str_t *name); 50 | 51 | ngx_stream_request_variable_value_t *ngx_stream_request_get_indexed_variable( 52 | ngx_stream_request_t *r, ngx_uint_t index); 53 | ngx_stream_request_variable_value_t *ngx_stream_request_get_flushed_variable( 54 | ngx_stream_request_t *r, ngx_uint_t index); 55 | 56 | ngx_stream_request_variable_value_t *ngx_stream_request_get_variable( 57 | ngx_stream_request_t *r, ngx_str_t *name, ngx_uint_t key); 58 | 59 | 60 | #if (NGX_PCRE) 61 | 62 | typedef struct { 63 | ngx_uint_t capture; 64 | ngx_int_t index; 65 | } ngx_stream_request_regex_variable_t; 66 | 67 | 68 | typedef struct { 69 | ngx_regex_t *regex; 70 | ngx_uint_t ncaptures; 71 | ngx_stream_request_regex_variable_t *variables; 72 | ngx_uint_t nvariables; 73 | ngx_str_t name; 74 | } ngx_stream_request_regex_t; 75 | 76 | 77 | typedef struct { 78 | ngx_stream_request_regex_t *regex; 79 | void *value; 80 | } ngx_stream_request_map_regex_t; 81 | 82 | 83 | ngx_stream_request_regex_t *ngx_stream_request_regex_compile(ngx_conf_t *cf, 84 | ngx_regex_compile_t *rc); 85 | ngx_int_t ngx_stream_request_regex_exec(ngx_stream_request_t *r, ngx_stream_request_regex_t *re, 86 | ngx_str_t *str); 87 | 88 | #endif 89 | 90 | 91 | typedef struct { 92 | ngx_hash_combined_t hash; 93 | #if (NGX_PCRE) 94 | ngx_stream_request_map_regex_t *regex; 95 | ngx_uint_t nregex; 96 | #endif 97 | } ngx_stream_request_map_t; 98 | 99 | 100 | void *ngx_stream_request_map_find(ngx_stream_request_t *r, ngx_stream_request_map_t *map, 101 | ngx_str_t *match); 102 | 103 | 104 | ngx_int_t ngx_stream_request_variables_add_core_vars(ngx_conf_t *cf); 105 | ngx_int_t ngx_stream_request_variables_init_vars(ngx_conf_t *cf); 106 | 107 | extern void ngx_stream_regular_var_name(ngx_str_t*); 108 | 109 | extern ngx_stream_request_variable_value_t ngx_stream_request_variable_null_value; 110 | extern ngx_stream_request_variable_value_t ngx_stream_request_variable_true_value; 111 | 112 | 113 | #endif /* _NGX_STREAM_VARIABLES_H_INCLUDED_ */ 114 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_cut_frame_module/config: -------------------------------------------------------------------------------- 1 | 2 | 3 | ngx_addon_name="ngx_stream_request_cut_frame_module" 4 | 5 | ngx_module_name="ngx_stream_request_cut_frame_module" 6 | ngx_module_srcs="$ngx_addon_dir/ngx_stream_request_cut_frame_module.c" 7 | ngx_module_type=STREAM 8 | ngx_module_incs=$ngx_addon_dir 9 | 10 | . auto/module 11 | 12 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_cut_frame_module/ngx_stream_request_cut_frame_module.c: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_stream_request_cut_frame_module.c 3 | // nginx-1.12 4 | // 5 | // Created by xpwu on 2019/1/31. 6 | // Copyright © 2019 xpwu. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define PROTOCOL_RESPONSE_SUCCESS 0 14 | #define PROTOCOL_RESPONSE_FAILED 1 15 | 16 | #ifdef this_module 17 | #undef this_module 18 | #endif 19 | #define this_module ngx_stream_request_cut_frame_module 20 | 21 | #ifdef core_module 22 | #undef core_module 23 | #endif 24 | #define core_module ngx_stream_request_core_module 25 | 26 | static void *ngx_stream_cut_frame_create_srv_conf(ngx_conf_t *cf); 27 | static char *ngx_stream_cut_frame_merge_srv_conf(ngx_conf_t *cf 28 | , void *parent, void *child); 29 | char *cut_frame_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 30 | 31 | 32 | static ngx_command_t ngx_stream_cut_frame_commands[] = { 33 | 34 | { ngx_string("cut_frame_protocol"), 35 | NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_NOARGS, 36 | cut_frame_conf, 37 | NGX_STREAM_SRV_CONF_OFFSET, 38 | 0, 39 | NULL }, 40 | 41 | 42 | ngx_null_command 43 | }; 44 | 45 | 46 | static ngx_stream_module_t ngx_stream_cut_frame_module_ctx = { 47 | NULL, 48 | NULL, /* postconfiguration */ 49 | 50 | NULL, /* create main configuration */ 51 | NULL, /* init main configuration */ 52 | 53 | ngx_stream_cut_frame_create_srv_conf, /* create server configuration */ 54 | ngx_stream_cut_frame_merge_srv_conf /* merge server configuration */ 55 | }; 56 | 57 | ngx_module_t ngx_stream_request_cut_frame_module = { 58 | NGX_MODULE_V1, 59 | &ngx_stream_cut_frame_module_ctx, /* module context */ 60 | ngx_stream_cut_frame_commands, /* module directives */ 61 | NGX_STREAM_MODULE, /* module type */ 62 | NULL, /* init master */ 63 | NULL, /* init module */ 64 | NULL, /* init process */ 65 | NULL, /* init thread */ 66 | NULL, /* exit thread */ 67 | NULL, /* exit process */ 68 | NULL, /* exit master */ 69 | NGX_MODULE_V1_PADDING 70 | }; 71 | 72 | 73 | // heartbeat 74 | typedef void (*start_heartbeat_timer)(); 75 | typedef void (*clear_heartbeat_timer_after_send_else)(); 76 | typedef void (*clear_heartbeat_timer)(); 77 | typedef void (*send_heartbeat)(); 78 | 79 | typedef struct { 80 | start_heartbeat_timer start; 81 | clear_heartbeat_timer_after_send_else clear_after_else; 82 | clear_heartbeat_timer clear; 83 | send_heartbeat send; 84 | } heartbeart; 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_fake_http_module/config: -------------------------------------------------------------------------------- 1 | 2 | 3 | ngx_addon_name="ngx_stream_request_fake_http_module" 4 | 5 | ngx_module_name="ngx_stream_request_fake_http_module" 6 | ngx_module_srcs="$ngx_addon_dir/ngx_stream_request_fake_http_module.c" 7 | ngx_module_type=STREAM 8 | ngx_module_incs=$ngx_addon_dir 9 | 10 | . auto/module 11 | 12 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_http_proxy_module/config: -------------------------------------------------------------------------------- 1 | 2 | 3 | ngx_addon_name="ngx_stream_request_http_proxy_module" 4 | 5 | ngx_module_name=ngx_stream_request_http_proxy_module 6 | ngx_module_srcs=$ngx_addon_dir/ngx_stream_request_http_proxy_module.c 7 | ngx_module_type=STREAM 8 | ngx_module_incs=$ngx_addon_dir 9 | 10 | . auto/module 11 | 12 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_lencontent_module/config: -------------------------------------------------------------------------------- 1 | 2 | 3 | ngx_addon_name="ngx_stream_request_lencontent_module" 4 | 5 | ngx_module_name=ngx_stream_request_lencontent_module 6 | ngx_module_srcs=$ngx_addon_dir/ngx_stream_request_lencontent_module.c 7 | ngx_module_type=STREAM 8 | ngx_module_incs=$ngx_addon_dir 9 | 10 | . auto/module 11 | 12 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_push_close_session_module/config: -------------------------------------------------------------------------------- 1 | 2 | 3 | ngx_addon_name="ngx_stream_request_push_close_session_module" 4 | 5 | ngx_module_name="ngx_stream_request_push_close_session_module" 6 | ngx_module_srcs="$ngx_addon_dir/ngx_stream_request_push_close_session_module.c" 7 | ngx_module_type=STREAM 8 | ngx_module_incs=$ngx_addon_dir 9 | 10 | . auto/module 11 | 12 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_push_close_session_module/ngx_stream_request_push_close_session_module.c: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_stream_request_push_data_module.c 3 | // nginx-1.12 4 | // 5 | // Created by xpwu on 2017/12/24. 6 | // Copyright © 2017年 xpwu. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #ifdef this_module 16 | #undef this_module 17 | #endif 18 | #define this_module ngx_stream_request_push_close_session_module 19 | 20 | #ifdef core_module 21 | #undef core_module 22 | #endif 23 | #define core_module ngx_stream_request_core_module 24 | 25 | typedef struct{ 26 | ngx_uint_t sub_protocol; 27 | ngx_int_t handler_index; 28 | } ngx_stream_request_push_close_session_svr_conf_t; 29 | 30 | static void *ngx_stream_request_push_close_session_create_srv_conf(ngx_conf_t *cf); 31 | static char *ngx_stream_request_push_close_session_merge_srv_conf(ngx_conf_t *cf 32 | , void *parent, void *child); 33 | 34 | static char *push_close_session_conf(ngx_conf_t *cf 35 | , ngx_command_t *cmd, void *conf); 36 | 37 | static ngx_command_t ngx_stream_push_close_session_commands[] = { 38 | 39 | { ngx_string("push_close_session_subprotocol"), 40 | NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1, 41 | push_close_session_conf, 42 | NGX_STREAM_SRV_CONF_OFFSET, 43 | 0, 44 | NULL }, 45 | 46 | ngx_null_command 47 | }; 48 | 49 | static ngx_stream_module_t ngx_stream_push_close_session_module_ctx = { 50 | NULL, 51 | NULL, /* postconfiguration */ 52 | 53 | NULL, /* create main configuration */ 54 | NULL, /* init main configuration */ 55 | 56 | ngx_stream_request_push_close_session_create_srv_conf, /* create server configuration */ 57 | ngx_stream_request_push_close_session_merge_srv_conf /* merge server configuration */ 58 | }; 59 | 60 | ngx_module_t ngx_stream_request_push_close_session_module = { 61 | NGX_MODULE_V1, 62 | &ngx_stream_push_close_session_module_ctx, /* module context */ 63 | ngx_stream_push_close_session_commands, /* module directives */ 64 | NGX_STREAM_MODULE, /* module type */ 65 | NULL, /* init master */ 66 | NULL, /* init module */ 67 | NULL, /* init process */ 68 | NULL, /* init thread */ 69 | NULL, /* exit thread */ 70 | NULL, /* exit process */ 71 | NULL, /* exit master */ 72 | NGX_MODULE_V1_PADDING 73 | }; 74 | 75 | static void *ngx_stream_request_push_close_session_create_srv_conf(ngx_conf_t *cf) { 76 | ngx_stream_request_push_close_session_svr_conf_t* pscf; 77 | pscf = ngx_palloc(cf->pool, sizeof(ngx_stream_request_push_close_session_svr_conf_t)); 78 | 79 | pscf->sub_protocol = NGX_CONF_UNSET_UINT; 80 | 81 | return pscf; 82 | } 83 | 84 | static char *ngx_stream_request_push_close_session_merge_srv_conf(ngx_conf_t *cf 85 | , void *parent, void *child) { 86 | ngx_stream_request_push_close_session_svr_conf_t* conf = child; 87 | ngx_stream_request_push_close_session_svr_conf_t* prev = parent; 88 | 89 | ngx_conf_merge_uint_value(conf->sub_protocol 90 | , prev->sub_protocol, NGX_CONF_UNSET_UINT); 91 | 92 | return NGX_CONF_OK; 93 | } 94 | 95 | static ngx_int_t handle_request(ngx_stream_request_t*); 96 | static ngx_int_t build_response(ngx_stream_request_t*); 97 | 98 | static char *push_close_session_conf(ngx_conf_t *cf 99 | , ngx_command_t *cmd, void *conf) { 100 | 101 | ngx_stream_request_push_close_session_svr_conf_t* pscf = conf; 102 | ngx_str_t* value = cf->args->elts; 103 | 104 | ngx_stream_request_handler_t* handler; 105 | 106 | handler = ngx_stream_request_add_handler(cf); 107 | pscf->handler_index = handler->index; 108 | handler->name = "push close session"; 109 | if (cf->args->nelts == 2) { 110 | handler->subprotocol_flag = ngx_atoi(value[1].data, value[1].len); 111 | } else { 112 | handler->subprotocol_flag = 1; // default subprotocol: 1 113 | } 114 | pscf->sub_protocol = handler->subprotocol_flag; 115 | handler->build_response = build_response; 116 | handler->handle_request = handle_request; 117 | 118 | return NGX_CONF_OK; 119 | } 120 | 121 | static ngx_int_t 122 | push_close_session_dist_hander(ngx_stream_request_t*); 123 | 124 | typedef struct{ 125 | ngx_int_t done; 126 | } request_src_ctx_t; 127 | 128 | static ngx_int_t handle_request(ngx_stream_request_t* r) { 129 | request_src_ctx_t* ctx = ngx_stream_request_get_module_ctx(r, this_module); 130 | if (ctx == NULL) { 131 | ctx = ngx_pcalloc(r->pool, sizeof(request_src_ctx_t)); 132 | ngx_stream_request_set_ctx(r, ctx, this_module); 133 | } 134 | if (ctx->done == 1) { 135 | return NGX_OK; 136 | } 137 | 138 | ctx->done = 1; 139 | 140 | return ngx_stream_request_push_to_dist_process(r 141 | , push_close_session_dist_hander); 142 | } 143 | 144 | static ngx_int_t build_response(ngx_stream_request_t* r) { 145 | r->data->buf->last = r->data->buf->pos; 146 | return NGX_OK; 147 | } 148 | 149 | static void finalize_async(ngx_event_t* event) { 150 | ngx_stream_session_t* s = event->data; 151 | ngx_stream_finalize_session_r_level(s, "push close session", NGX_LOG_NOTICE); 152 | } 153 | 154 | ngx_int_t 155 | push_close_session_dist_hander(ngx_stream_request_t* r) { 156 | r->data->buf->last = r->data->buf->pos; 157 | r->data->next = NULL; 158 | 159 | ngx_event_t* e = ngx_pcalloc(r->pool, sizeof(ngx_event_t)); 160 | e->handler = finalize_async; 161 | e->data = r->session; 162 | e->log = r->session->connection->log; 163 | 164 | ngx_post_event(e, &ngx_posted_events); 165 | 166 | return NGX_OK; 167 | } 168 | 169 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_push_data_module/config: -------------------------------------------------------------------------------- 1 | 2 | 3 | ngx_addon_name="ngx_stream_request_push_data_module" 4 | 5 | ngx_module_name="ngx_stream_request_push_data_module" 6 | ngx_module_srcs="$ngx_addon_dir/ngx_stream_request_push_data_module.c" 7 | ngx_module_type=STREAM 8 | ngx_module_incs=$ngx_addon_dir 9 | 10 | . auto/module 11 | 12 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_push_data_module/ngx_stream_request_push_data_module.c: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_stream_request_push_data_module.c 3 | // nginx-1.12 4 | // 5 | // Created by xpwu on 2017/12/24. 6 | // Copyright © 2017年 xpwu. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #ifdef this_module 16 | #undef this_module 17 | #endif 18 | #define this_module ngx_stream_request_push_data_module 19 | 20 | #ifdef core_module 21 | #undef core_module 22 | #endif 23 | #define core_module ngx_stream_request_core_module 24 | 25 | typedef struct{ 26 | ngx_uint_t sub_protocol; 27 | ngx_int_t handler_index; 28 | } ngx_stream_request_push_data_svr_conf_t; 29 | 30 | static void *ngx_stream_request_push_data_create_srv_conf(ngx_conf_t *cf); 31 | static char *ngx_stream_request_push_data_merge_srv_conf(ngx_conf_t *cf 32 | , void *parent, void *child); 33 | 34 | static char *push_data_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 35 | 36 | static ngx_command_t ngx_stream_push_data_commands[] = { 37 | 38 | { ngx_string("push_data_subprotocol"), 39 | NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1, 40 | push_data_conf, 41 | NGX_STREAM_SRV_CONF_OFFSET, 42 | 0, 43 | NULL }, 44 | 45 | ngx_null_command 46 | }; 47 | 48 | static ngx_stream_module_t ngx_stream_push_data_module_ctx = { 49 | NULL, 50 | NULL, /* postconfiguration */ 51 | 52 | NULL, /* create main configuration */ 53 | NULL, /* init main configuration */ 54 | 55 | ngx_stream_request_push_data_create_srv_conf, /* create server configuration */ 56 | ngx_stream_request_push_data_merge_srv_conf /* merge server configuration */ 57 | }; 58 | 59 | ngx_module_t ngx_stream_request_push_data_module = { 60 | NGX_MODULE_V1, 61 | &ngx_stream_push_data_module_ctx, /* module context */ 62 | ngx_stream_push_data_commands, /* module directives */ 63 | NGX_STREAM_MODULE, /* module type */ 64 | NULL, /* init master */ 65 | NULL, /* init module */ 66 | NULL, /* init process */ 67 | NULL, /* init thread */ 68 | NULL, /* exit thread */ 69 | NULL, /* exit process */ 70 | NULL, /* exit master */ 71 | NGX_MODULE_V1_PADDING 72 | }; 73 | 74 | static void *ngx_stream_request_push_data_create_srv_conf(ngx_conf_t *cf) { 75 | ngx_stream_request_push_data_svr_conf_t* pscf; 76 | pscf = ngx_palloc(cf->pool, sizeof(ngx_stream_request_push_data_svr_conf_t)); 77 | 78 | pscf->sub_protocol = NGX_CONF_UNSET_UINT; 79 | 80 | return pscf; 81 | } 82 | 83 | static char *ngx_stream_request_push_data_merge_srv_conf(ngx_conf_t *cf 84 | , void *parent, void *child) { 85 | ngx_stream_request_push_data_svr_conf_t* conf = child; 86 | ngx_stream_request_push_data_svr_conf_t* prev = parent; 87 | 88 | ngx_conf_merge_uint_value(conf->sub_protocol 89 | , prev->sub_protocol, NGX_CONF_UNSET_UINT); 90 | 91 | return NGX_CONF_OK; 92 | } 93 | 94 | static ngx_int_t handle_request(ngx_stream_request_t*); 95 | static ngx_int_t build_response(ngx_stream_request_t*); 96 | 97 | static char *push_data_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { 98 | 99 | ngx_stream_request_push_data_svr_conf_t* pscf = conf; 100 | ngx_str_t* value = cf->args->elts; 101 | 102 | ngx_stream_request_handler_t* handler; 103 | 104 | handler = ngx_stream_request_add_handler(cf); 105 | pscf->handler_index = handler->index; 106 | handler->name = "push data"; 107 | if (cf->args->nelts == 2) { 108 | handler->subprotocol_flag = ngx_atoi(value[1].data, value[1].len); 109 | } else { 110 | handler->subprotocol_flag = 0; // default subprotocol: 0 111 | } 112 | pscf->sub_protocol = handler->subprotocol_flag; 113 | handler->build_response = build_response; 114 | handler->handle_request = handle_request; 115 | 116 | return NGX_CONF_OK; 117 | } 118 | 119 | static ngx_int_t 120 | push_data_dist_hander(ngx_stream_request_t*); 121 | 122 | typedef struct{ 123 | ngx_int_t done; 124 | } request_src_ctx_t; 125 | 126 | static ngx_int_t handle_request(ngx_stream_request_t* r) { 127 | request_src_ctx_t* ctx = ngx_stream_request_get_module_ctx(r, this_module); 128 | if (ctx == NULL) { 129 | ctx = ngx_pcalloc(r->pool, sizeof(request_src_ctx_t)); 130 | ngx_stream_request_set_ctx(r, ctx, this_module); 131 | } 132 | if (ctx->done == 1) { 133 | return NGX_OK; 134 | } 135 | 136 | return ngx_stream_request_push_to_dist_process(r, push_data_dist_hander); 137 | } 138 | 139 | static ngx_int_t build_response(ngx_stream_request_t* r) { 140 | r->data->buf->last = r->data->buf->pos; 141 | return NGX_OK; 142 | } 143 | 144 | ngx_int_t 145 | push_data_dist_hander(ngx_stream_request_t* r) { 146 | ngx_stream_handle_request_from(r, -1, 1); 147 | return NGX_OK; 148 | } 149 | 150 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_push_module/config: -------------------------------------------------------------------------------- 1 | 2 | 3 | ngx_addon_name="ngx_stream_request_push_module" 4 | 5 | ngx_module_name="ngx_stream_request_push_module" 6 | ngx_module_srcs="$ngx_addon_dir/ngx_stream_request_push_module.c" 7 | ngx_module_deps="$ngx_addon_dir/ngx_stream_request_push_module.h" 8 | ngx_module_type=STREAM 9 | ngx_module_incs=$ngx_addon_dir 10 | 11 | . auto/module 12 | 13 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_push_module/ngx_stream_request_push_module.h: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_stream_request_push_module.h 3 | // nginx-1.12 4 | // 5 | // Created by xpwu on 2017/12/23. 6 | // Copyright © 2017年 xpwu. All rights reserved. 7 | // 8 | 9 | #ifndef ngx_stream_request_push_module_h 10 | #define ngx_stream_request_push_module_h 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | // 通过r->data的buffer位置与 ctx->msg的buffer位置 自动判断是否需要重新分配空间 18 | // 具体见 need_copy_data 的实现 19 | 20 | // NGX_OK; NGX_ERROR; NGX_AGAIN; 21 | // 如果返回NGX_AGAIN,在后续流程中需要调用 22 | // ngx_stream_request_push_back_src_process 把request返回原进程 23 | // 执行结束后,必须保证r仍然有效,否则会crash。r中的data就是执行后返回的数据 24 | typedef ngx_int_t 25 | (*ngx_stream_request_push_dist_hander)(ngx_stream_request_t*); 26 | 27 | // NGX_OK; NGX_ERROR; NGX_AGAIN 28 | extern ngx_int_t 29 | ngx_stream_request_push_to_dist_process(ngx_stream_request_t*, 30 | ngx_stream_request_push_dist_hander); 31 | 32 | extern void 33 | ngx_stream_request_push_back_src_process(ngx_stream_request_t*); 34 | 35 | 36 | #endif /* ngx_stream_request_push_module_h */ 37 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_set_module/config: -------------------------------------------------------------------------------- 1 | 2 | 3 | ngx_addon_name="ngx_stream_request_set_module" 4 | 5 | ngx_module_name=ngx_stream_request_set_module 6 | ngx_module_srcs=$ngx_addon_dir/ngx_stream_request_set_module.c 7 | ngx_module_type=STREAM 8 | ngx_module_incs=$ngx_addon_dir 9 | 10 | . auto/module 11 | 12 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_set_module/ngx_stream_request_set_module.c: -------------------------------------------------------------------------------- 1 | // 2 | // ngx_stream_set_module.c 3 | // nginx-1.12 4 | // 5 | // Created by xpwu on 2017/12/17. 6 | // Copyright © 2017年 xpwu. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #ifdef this_module 14 | #undef this_module 15 | #endif 16 | #define this_module ngx_stream_request_set_module 17 | 18 | #ifdef core_module 19 | #undef core_module 20 | #endif 21 | #define core_module ngx_stream_request_core_module 22 | 23 | static char * ngx_stream_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 24 | static ngx_int_t ngx_stream_set_get_variable (ngx_stream_request_t *r, 25 | ngx_stream_variable_value_t * 26 | , uintptr_t data); 27 | 28 | static ngx_command_t ngx_stream_set_commands[] = { 29 | 30 | { ngx_string("rset"), 31 | NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2, 32 | ngx_stream_set, 33 | NGX_STREAM_SRV_CONF_OFFSET, 34 | 0, 35 | NULL }, 36 | 37 | ngx_null_command 38 | }; 39 | 40 | 41 | static ngx_stream_module_t ngx_stream_set_module_ctx = { 42 | NULL, /* preconfiguration */ 43 | NULL, /* postconfiguration */ 44 | 45 | NULL, /* create main configuration */ 46 | NULL, /* init main configuration */ 47 | 48 | NULL, /* create server configuration */ 49 | NULL /* merge server configuration */ 50 | }; 51 | 52 | ngx_module_t ngx_stream_request_set_module = { 53 | NGX_MODULE_V1, 54 | &ngx_stream_set_module_ctx, /* module context */ 55 | ngx_stream_set_commands, /* module directives */ 56 | NGX_STREAM_MODULE, /* module type */ 57 | NULL, /* init master */ 58 | NULL, /* init module */ 59 | NULL, /* init process */ 60 | NULL, /* init thread */ 61 | NULL, /* exit thread */ 62 | NULL, /* exit process */ 63 | NULL, /* exit master */ 64 | NGX_MODULE_V1_PADDING 65 | }; 66 | 67 | static char * ngx_stream_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { 68 | ngx_str_t *value; 69 | ngx_stream_request_compile_complex_value_t ccv; 70 | ngx_stream_request_variable_t *v; 71 | 72 | value = cf->args->elts; 73 | 74 | ngx_memzero(&ccv, sizeof(ngx_stream_request_compile_complex_value_t)); 75 | 76 | ccv.cf = cf; 77 | ccv.value = &value[2]; 78 | ccv.complex_value = ngx_pcalloc(cf->pool, sizeof(ngx_stream_request_complex_value_t)); 79 | if (ngx_stream_request_compile_complex_value(&ccv) != NGX_OK) { 80 | return NGX_CONF_ERROR; 81 | } 82 | 83 | ngx_str_t* var = &value[1]; 84 | if (var->data[0] == '$') { 85 | var->data += 1; 86 | var->len -= 1; 87 | } 88 | v = ngx_stream_request_add_variable(cf, var, 0); 89 | 90 | if (v == NULL) { 91 | return NGX_CONF_ERROR; 92 | } 93 | v->data = (uintptr_t)ccv.complex_value; 94 | v->flags = 0; 95 | v->get_handler =ngx_stream_set_get_variable; 96 | 97 | return NGX_CONF_OK; 98 | } 99 | 100 | static ngx_int_t ngx_stream_set_get_variable (ngx_stream_request_t *r, 101 | ngx_stream_variable_value_t *value 102 | , uintptr_t data) { 103 | ngx_stream_request_complex_value_t *complex = (ngx_stream_request_complex_value_t*)data; 104 | ngx_str_t text; 105 | 106 | if (ngx_stream_request_complex_value(r, complex, &text) != NGX_OK) { 107 | return NGX_ERROR; 108 | } 109 | 110 | value->len = (unsigned)text.len; 111 | value->data = text.data; 112 | value->valid = (value->data!=NULL)?1:0; 113 | value->not_found = (value->len==0&&value->data==NULL)?1:0; 114 | value->no_cacheable = (value->len==0||value->data==NULL)?1:0; 115 | 116 | return NGX_OK; 117 | } 118 | 119 | -------------------------------------------------------------------------------- /stream_module/ngx_stream_request_websocket_module/config: -------------------------------------------------------------------------------- 1 | 2 | 3 | ngx_addon_name="ngx_stream_request_websocket_module" 4 | 5 | ngx_module_name=ngx_stream_request_websocket_module 6 | ngx_module_srcs=$ngx_addon_dir/ngx_stream_request_websocket_module.c 7 | ngx_module_type=STREAM 8 | ngx_module_incs=$ngx_addon_dir 9 | 10 | . auto/module 11 | 12 | --------------------------------------------------------------------------------