GithubHelp home page GithubHelp logo

cocoahttpserver's Introduction

CocoaHTTPServer

Build Status Version Platform License

CocoaHTTPServer is a small, lightweight, embeddable HTTP server for Mac OS X or iOS applications.

Sometimes developers need an embedded HTTP server in their app. Perhaps it's a server application with remote monitoring. Or perhaps it's a desktop application using HTTP for the communication backend. Or perhaps it's an iOS app providing over-the-air access to documents. Whatever your reason, CocoaHTTPServer can get the job done. It provides:

  • Built in support for bonjour broadcasting
  • IPv4 and IPv6 support
  • Asynchronous networking using GCD and standard sockets
  • Password protection support
  • SSL/TLS encryption support
  • Extremely FAST and memory efficient
  • Extremely scalable (built entirely upon GCD)
  • Heavily commented code
  • Very easily extensible
  • WebDAV is supported too!

Can't find the answer to your question in any of the [wiki](https://github.com/robbiehanson/CocoaHTTPServer/wiki) articles? Try the **[mailing list](http://groups.google.com/group/cocoahttpserver)**.

Love the project? Wanna buy me a coffee? (or a beer :D) [![donation](http://www.paypal.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BHF2DJRETGV5S)

cocoahttpserver's People

Contributors

arlol avatar chrisballinger avatar dirkx avatar ieswxia avatar jpsimons avatar kkazuo avatar matthewrayfield avatar plelevier avatar programmation avatar robbiehanson avatar skyebook avatar snej avatar swisspol avatar vgavrilov avatar vronin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cocoahttpserver's Issues

Add support for gzip encoding

Currently the Accept-Encoding: gzip or compress is not implemented.
Sadly this is one big feature, especially for mobile devices which might have low bandwidth or ever a monthly volume limit.

It might on most cases even improve performance client side.

+[HTTPServer bonjourThread] crash

Hello everyone, I used CocoaHTTPServer in my project, now I met one problem.
My program always crashes at this line:

HTTPServer.m line 757
+[HTTPServer bonjourThread]

It's not appears every time, I catch it in my app crash log. I don't know if I did something wrong, or it is some multithread problems. I didn't find anything on the internet. does any can help me?

Permission denied when starting server on port 80

Great job with CocoaHTTPServer - it's very useful and easy to setup. When I try to start a site on port 80, however, I get the following error (port 12345 works fine). I'm using the same code as in the SimpleHTTPServer AppDelegate, with the setPort line uncommented. I see that this is a permissions error, so if applicable, sandboxing is disabled. Thanks for your help.

2013-01-07 23:15:29:762 SimpleHTTPServer[14086:303] HTTPServer: Failed to start HTTP Server: Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied" UserInfo=0x10280c4d0 {NSLocalizedDescription=Permission denied, NSLocalizedFailureReason=Error in bind() function}

2013-01-07 23:15:29:762 SimpleHTTPServer[14086:303] Error starting HTTP Server: Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied" UserInfo=0x10280c4d0 {NSLocalizedDescription=Permission denied, NSLocalizedFailureReason=Error in bind() function}

Stalls on large WebDAV writes

I'm attempting to use CocoaHTTPServer/WebDAV to upload some significantly large files via the Finder to my iOS application. Files on the order of 4GB. I mount up the Documents directory for my iOS application with WebDAV in the Finder and just drag copy the files.

I've been seeing problems where after about 90 to 100 seconds the Finder throws up an error -36 saying that there was a problem reading/writing data to my file.

I've been looking at this with Wireshark and I see a nice sequences of packet writes from my Mac, followed by sequences of ACKs from the iOS device. This goes on for a while. Then, there's a long pause of 6 seconds, then the Mac reports a TCP ZeroWindow, and then it all goes to hell after that.

I have a captured Wireshark trace, but it's over 400MB. I have a screen shot that I've uploaded http://img100.imageshack.us/img100/7285/wiresharkh.png that shows the portion I'm talking about. Between packet 315017 and 315018 there's a 6 second pause. Then the ZeroWindows, and then more long pauses.

Cannot build with target <=iOS4.3 because wrong declarion of delegate in MultipartFormDataParse

When I set sdk target to <=4.3, the building is failt and XCode throw this error:

CompileC /Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Intermediates/iCeeNee.build/Debug-iphonesimulator/iCeeNee.build/Objects-normal/i386/MultipartFormDataParser.o iCeeNee/Mime/MultipartFormDataParser.m normal i386 objective-c com.apple.compilers.llvm.clang.1_0.compiler
    cd /Users/kureikain/Documents/iCeeNee
    setenv LANG en_US.US-ASCII
    setenv PATH "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c -arch i386 -fmessage-length=0 -std=gnu99 -fobjc-arc -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototypes -Wreturn-type -Wno-implicit-atomic-properties -Wformat -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-sign-compare -Wno-shorten-64-to-32 -Wpointer-sign -Wno-newline-eof -Wno-selector -Wno-strict-selector-match -Wno-undeclared-selector -Wno-deprecated-implementations -DDEBUG=1 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk -fexceptions -fasm-blocks -Wprotocol -Wdeprecated-declarations -mmacosx-version-min=10.6 -g -Wno-conversion -Wno-sign-conversion -fobjc-abi-version=2 -fobjc-legacy-dispatch "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -D__IPHONE_OS_VERSION_MIN_REQUIRED=40200 -iquote /Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Intermediates/iCeeNee.build/Debug-iphonesimulator/iCeeNee.build/iCeeNee-generated-files.hmap -I/Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Intermediates/iCeeNee.build/Debug-iphonesimulator/iCeeNee.build/iCeeNee-own-target-headers.hmap -I/Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Intermediates/iCeeNee.build/Debug-iphonesimulator/iCeeNee.build/iCeeNee-all-target-headers.hmap -iquote /Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Intermediates/iCeeNee.build/Debug-iphonesimulator/iCeeNee.build/iCeeNee-project-headers.hmap -I/Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Products/Debug-iphonesimulator/include -I/Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Intermediates/iCeeNee.build/Debug-iphonesimulator/iCeeNee.build/DerivedSources/i386 -I/Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Intermediates/iCeeNee.build/Debug-iphonesimulator/iCeeNee.build/DerivedSources -F/Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Products/Debug-iphonesimulator -include /Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Intermediates/PrecompiledHeaders/iCeeNee-Prefix-dlsilurfcylmyjcvrangxnrfggqn/iCeeNee-Prefix.pch -MMD -MT dependencies -MF /Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Intermediates/iCeeNee.build/Debug-iphonesimulator/iCeeNee.build/Objects-normal/i386/MultipartFormDataParser.d --serialize-diagnostics /Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Intermediates/iCeeNee.build/Debug-iphonesimulator/iCeeNee.build/Objects-normal/i386/MultipartFormDataParser.dia -c /Users/kureikain/Documents/iCeeNee/iCeeNee/Mime/MultipartFormDataParser.m -o /Users/kureikain/Library/Developer/Xcode/DerivedData/iCeeNee-frqthfwiitgyrpbsvxcefrvstlua/Build/Intermediates/iCeeNee.build/Debug-iphonesimulator/iCeeNee.build/Objects-normal/i386/MultipartFormDataParser.o

/Users/kureikain/Documents/iCeeNee/iCeeNee/Mime/MultipartFormDataParser.m:41:13: error: existing ivar 'delegate' for __weak property 'delegate' must be __weak
@synthesize delegate,formEncoding;
            ^
/Users/kureikain/Documents/iCeeNee/iCeeNee/Mime/MultipartFormDataParser.h:58:31: note: property declared here
@property(weak, readwrite) id delegate;

I line 45-52, file MultipartFirmDataParser.h we declared ivar delegate:

#if __has_feature(objc_arc_weak)
    __weak id<MultipartFormDataParserDelegate>                  delegate;
#else
    __unsafe_unretained id<MultipartFormDataParserDelegate>     delegate;
#endif  
    int                                 currentEncoding;
    NSStringEncoding                    formEncoding;
}                       

but later on, when we delare property, we didn't do that:

@property(weak, readwrite) id delegate;

The fixed is to check if we have objc_arc_weak or not. If not, we use unsafe_unretained instead of.

Compile error with Xcode 4.6, for Mac target

CocoaHTTPServer fails to build for Mac OS targets using Xcode 4.6. It looks like Clang's control-flow analysis has been improved and it now detects an uninitialized-variable error in GCDAsyncSocket:


CocoaHTTPServer/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m:4214:6: error: variable 'hasBytesAvailable' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized]
        if ([self usingCFStreamForTLS])
            ^~~~~~~~~~~~~~~~~~~~~~~~~~
CocoaHTTPServer/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m:4275:7: note: uninitialized use occurs here
        if ((hasBytesAvailable == NO) && ([preBuffer availableBytes] == 0))
             ^~~~~~~~~~~~~~~~~

I think this will not be a real bug because it doesn't look as though usingCFStreamForTLS will ever be set when not building for iOS, but I'm not certain.

I haven't looked at the CocoaAsyncSocket project to see if they've fixed the bug there.

Multi-part file upload combined with https fails especially via WAN

First of all, thank you for your great HTTP server library.
Really made creating a remote api for our app so much easier.

We have a little issue with file upload via a form to the http server and https. When users try to upload a file via the Internet (wan) the server doesn't seem to respond to the initial tcp packet anymore.

Via internal LAN address it works fine, via remote (3g, wan, external) the file upload freezes.
Always reproducible.

I'll attach the minimum test application, which is a simple combination of the file upload and secure server example.

Simple example project:
http://cl.ly/3Y390e1v0L3V

If I just disable the Secure server ( return NO; ) it works fine.
The combination of SSL and multi-part seems broken.

Add run-time information to CocoaHTTPServer using custom Response class

I have the following code to start my own Cocoa HTTP Server. In order to manually handle the responses I have created my custom HTTPConnection class named PictureHTTPConnection

self.httpServer = [[HTTPServer alloc]init];
self.httpServer.type = @"_http._tcp.";
self.httpServer.name = @"MyBonjour Name";
self.httpServer.connectionClass = [PictureHTTPConnection class];

The problem here is that the PictureHTTPConnection class needs some information in order to handle the HTTP connections. However, I only provide the class and therefore I don't have a reference to the instance. I could do something with global data but this is not very good programming practise.

The best way I can think of is setting the PictureHTTPConnection's delegate to the UIApplicationDelegate so that it can answer any callbacks. :-(

A new version release?

The last version 2.2.1 was released last year. There are some rather important updates in this year, is it possible to tag a new version?

WebSocket not working with Firefox 11

I fixed it by changing the following line in WebSocket.m :

else if (![connectionHeaderValue caseInsensitiveCompare:@"Upgrade"] == NSOrderedSame) {
isWebSocket = NO;
}

To :

else if ([connectionHeaderValue rangeOfString:@"Upgrade"].location == NSNotFound) {
isWebSocket = NO;
}

(firefox was sending a "keepalive" prefix in connectionHeaderValue)
Don't know if that the better way to do it(maybe it would be better to check only the end of the string, i don't know what says the specs) but it works

Multipart response data from server on iphone/ipad

First of all, thank you for your great HTTP server library.

I have a question about response mjpeg(motion jpeg) data from server.
My iphone will create a mjpeg data and store each frame in a queue, when a request comes in, I will return each frame by dequeue action.
I would like to know how to make response supported "multipart", then I can response frame continually.

Use HTTPDataResponse or HTTPFileResponse is better for this situation.

Thanks

Stream video with CocoaHttpServer

Hi

I want to use this code in my app for streaming video from my iPhone to another iPhone on the same WiFi.
my problem is that i want to download it in the first iPhone and in the time i download it i want the second iphone will start download it.

I send the file with this method(in the HttpConnection):

            NSData *tmpData = [NSData dataWithContentsOfFile:filePath];
    return [[[HTTPDataResponse alloc] initWithData:tmpData] autorelease];

my problem is that:
the first iPhone sent it but only the KB that he download until the request and the rest of the file is not sent to the second iPhone.

any idea how can i fix it?

How can i use HTTP Server code for raw request /response by client

Hi

I want to use http server code for both send/recv http request/response,as well as normal client request/responses(not http header request/responses).

If i am using the same server for normal client request/responses,after 1 minute the client connection is disconnecting by StreamEndEvent occurred.

Please give answer thanks

How can I make the connection never time out?

I created a "HTTPConnection" subclass to serve dynamic contents. And store the connection informations as its instance variables.

However, looks like the CocoaHTTPServer will initiate a new connection if the current connection doesn't have any action for more than 1 minute. So all my variables will be reset if the user refresh the page after a more than 1 minute idle.

I tried to override the "shouldDie" methods, but it doesn't work:

  • (BOOL)shouldDie
    {
    return NO;
    }

Any help is appreciated, thanks a lot!

Client-side support in WebSocket class

It would be useful if the WebSocket class supported opening a WebSocket as a client, e.g. via an initializer like

- (instancetype)initWithAddress:(NSData *)remoteAddr error:(NSError **)errPtr;

I realize this is a server-side framework, but WebSocket is very useful as a transport for P2P apps (such as one I'm working on), which will need to implement both sides. It seems wasteful for an app to have to add an entirely different WebSocket client implementation such as SocketRocket, when it probably takes only a few lines of code to add client-side support to the WebSocket class.

HTTPRouter

Hi Robbie!

I was looking into web services for OBJ-C recently and someone mentioned this, after I had found froth kit, I was deciding to go and try to modernize froth kit, but it was a mess and super old. Gladly I was able to find this awesome project which seems to be nice light weight and active!!

So now my presentation I worked on an awesome sub Class of HTTPConnection and added blocked based routing! It makes writing a server crazy simple now! I would love to have a chat and see where you are and how we can move all of CHS more in this direction, next I was going to add a way to link in automatic session management and basic user logins, I'm going for a lean and lightweight webstack for making api's and w/e else you can think of.

So without further ado here is simple server using my Routing class

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Initalize our http server
    httpServer = [[HTTPServer alloc] init];
    [httpServer setType:@"_http._tcp."];                //Bounjour
    [httpServer setPort:12345];
    [httpServer setConnectionClass:[HTTPRouter class]]; // User router

    //Setup some sample routes

    //Regex? o.O and query params why not?
    [HTTPRouter handleRoute:@"[tb]est" withBlock:^(HTTPMessage* message)
    {
        return [NSString stringWithFormat:@"Test Params:%@", message.params];
    }];

    //Static route
    [HTTPRouter handleRoute:@"test/hello" withBlock:^(HTTPMessage* message)
    {
        return @"HAHAHAH WHAT ARE U DOING? Hello world is so old school";
    }];

    //Dynamic routes, stored as params :key, sinartra anyone? oops don't tell them i did this
    [HTTPRouter handleRoute:@"laughs/:times" withBlock:^(HTTPMessage* message)
    {
        NSInteger times = [[message.params valueForKey:@"times"] integerValue];
        NSMutableString *response = [NSMutableString string];

        for (int i = 0; i < times; i++)
        {
            [response appendString:@"HA"];
        }

        return response;
    }];

    // Start the server (and check for problems)
    NSError *error;
    BOOL success = [httpServer start:&error];
    NSAssert(success, @"Error starting HTTP Server: %@", error);

}

And here is it's current implementation
https://gist.github.com/2650888

I would love for this to become part of CocoaHTTPServer and maybe influence it's future! I look forward to talking with you! I would also like to inform you, this was whipped together, so there are still some things to resolve, and bug test. Such as freeing the yucky global used to store the blocks and their routes. But this can all be addressed :) It may also be useful to note the return types currently supported by blocks are NSString, NSData, NSDictionary, NSArray, the later 2 will be serialized using NSJSONSerialization.

Remove ARC

It's a bit of an odd move to move to an ARC only solution for a library like this one.
Sadly this will mean all projects have to have a minimum requirement of 64bit intel processors because ARC doesn't work on 32bit processors.

Please move back to old fashioned memory management or even better: like other libraries do: hybrid.

WebSocket class has no prefix: causes conflict

Hi Robbie:

I've been happily using CocoaHTTPServer for some time now. Recently, for a client project, I integrated a realtime messaging framework from a third party that uses UnittWebSocketClient. This project also has a class named WebSocket:

http://code.google.com/p/unitt/source/browse/projects/iOS/UnittWebSocketClient/trunk/UnittWebSocketClient/WebSocket.h

I'm a bit surprised that neither that project's class nor the one you use has a prefix (e.g. RHWebSocket). I'm happy to make this change if you let me know what prefix you'd like to use.

If I've missed something, I'd love to know what.

Meanwhile, thanks again for releasing this incredibly useful code.

Best,

John

Handling multiple concurrent connections?

Hello, I'm trying to work through some concurrency issues with my application. This seems obvious, but I can't find it documented anywhere - am I right in thinking that CocaHTTPServer supports handling multiple concurrent connections, out of the box? I presumed it did, and then I noticed that serverQueue and connectionQueue in HTTPServer.m are both serial queues, and that the comment in - (HTTPConfig *)config (line 545) suggests not.

Setting Domain For Bonjour

Hey,

I've found (using the iOS example) that setting the domain to anything other than local. causes the Bonjour service to fail to publish.

It also seems that

- (void)netService:(NSNetService *)ns didNotPublish:(NSDictionary *)errorDict

is never called so I'm unable to inspect errorDict.

Any ideas?

Regards,

-Mic

Digest auth nonce should timeout only x seconds after last use

As currently implemented, a digest authentication recent nonce is removed from the recentNonces array after 300 seconds. This is a problem because browsers such as Chrome, Firefox (and Safari if the password is not saved) will re-prompt the user for user/password as soon as the 300 seconds are up.

The better way to implement this would be to have the nonce time out only 300 seconds after the last use of said nonce, not 300 seconds after it was created.

dispatch_get_current_queue usage at risk

There appear to be 89 uses of dispatch_get_current_queue in the CocoaHTTPServer source. The headers for that API say "Recommended for debugging and logging purposes only" and Apple has gone out of its way lately to state that the API is unreliable, especially under ARC. If one were to look at certain SDKs that may or may not yet be public they might find even more stern wording.

A lot of this usage seems benign and easily removable — it either synchronously or asynchronously invokes the block based on whether or not the desired queue is already in use — but other areas seem fundamentally built around the concept.

It seems like storing context data on queue creation with dispatch_queue_set_specific, then reading it out with dispatch_get_specific, is the way to go moving forward for the kind of checks this project is currently using dispatch_get_current_queue to perform.

CRASH: index 0 beyond bounds for empty array

* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'

HTTPConnection.m:1477
DDRange range = [[ranges objectAtIndex:rangeIndex] ddrangeValue];

Status 000

Robbie, while working with TouchDB's peer to peer replication I came across the situation that CocoaHTTPServer would return a response with status code 0. I've tracked this down to originate from

        // Default status code: 200 - OK
        NSInteger status = 200;

        if ([httpResponse respondsToSelector:@selector(status)])
        {
            status = [httpResponse status];
        }

in HTTPConnection.m:1174 (revision 37a7814). Apparently I've hit the case where an uninitialized (?) httpResponse is being queried for its status and returns 0.

The debugger output at this point is:

(lldb) po httpResponse
2012-05-04 11:37:04.147 App[9404:707] >>>>>> 1 docs being updated
(NSObject *) $5 = 0x1de81b20 Response[GET /app_test/_local/bfca65ed062d9d28d05dd2e37eceda78c31e7914]
(lldb) po [httpResponse status]
(id) $6 = 0x00000000 <nil>

The custom response class of the TouchDB project is TDResponse and since httpResponse is of NSObject this seems to indicate that the problem may not be originating in TouchDB. (Though I understand far too little of the whole machinery, I have to admit.)

When I assume that the "true" default of status should be 200 and therefore change HTTPConnection accordingly, like so:

        if ([httpResponse respondsToSelector:@selector(status)] && [httpResponse status] != 0)
        {
            status = [httpResponse status];
        }

I find that the server works for me. Is this a feasible approach? Or is there something wrong at a deeper level and httpResponse.status should never happen to return 0?

Cheers,
Sven

CocoaHTTPServer sometimes fails to establish SSL connection

I run SecureHTTPServer and quite often when i try to open a page it fails. I investigated this problem and found that for some reason in GCDAsyncSocket ssl_continueSSLHandshake, on SSLHashshake(sslContext) it returns error errSSLCrypto.

If it fails then there will be no popup which requires to allow access to keychain. I am not sure whether it's causes problem or effect of this problem.

I have OS 10.7.5

Recent nonces in HTTP authentication are not removed

The nonces created for HTTP digest authentication are not removed as they should be.

In the method generateNonce in HTTPConnection.m, the scheduled timer to remove recent nonces does not fire.

In order for the timer to fire, it should be called from the main thread where a run loop is guaranteed to exist. I think it should be called as follows.

dispatch_async(dispatch_get_main_queue(), ^{
    [NSTimer scheduledTimerWithTimeInterval:TIMEOUT_NONCE
                                     target:[HTTPConnection class]
                                   selector:@selector(removeRecentNonce:)
                                   userInfo:newNonce
                                    repeats:NO];
});

Please let me know if there is any issues with the call above.

WebSocket - (void)didClose method not called when closed in Chrome

The easiest way to show this is to open up the SimpleWebSocketServer
Open Web/WebSocketTest2.js and change line 14 from:

ws.onmessage = function(evt) { alert("received: " + evt.data); };

to:

ws.onmessage = function(evt) { alert("received: " + evt.data); ws.close(); };

Running in Firefox/Safari you will see "MyWebSocket[0x7fbb9ad003a0]: didClose" in the console output.

When running in Chrome this method is never call.

HTTP Server not running in background

Is it possible to keep the server running in the back ground if the user jumps to a different app or the home button is pressed??

I see there is an app on the MArket that does this.

iPhoneHTTPServer Sample working on simulator but not on device.

Greetings I have implemented this in an iPhone App but neither my App nor the Sample iPhoneHTTPServer work for the device, they do work in the simulator though.

When I use the wifiIP:port on my Mac(using any browser) which is on the same network of the iPhone it simply won't open the Page, but it doesn t give a 404 error either. Its like the page is there but it can't connect.

"Unable to connect" "Firefox can't establish a connection to the server at 192.168.0.102:52395."
"The site could be temporarily unavailable or too busy. Try again in a few
moments.
If you are unable to load any pages, check your computer's network
connection.
If your computer or network is protected by a firewall or proxy, make sure
that Firefox is permitted to access the Web."

Any idea what might be causing this? I know I have to disable my Mac OS X firewall when I want to share a website on the local network is there something similar for the iPhone App?

thanks

external access

if I do not have a wi-fi or 3G, the server does not work. Is there a way to not depend on the external connection?

range parse bug

when parsing [#]-[#] your second if error check currently is:
if(r2 >= contentLength) return NO;
but should be:
if(r2 - r1 >= contentLength) return NO;

CocoaLumberjack should be optional -- use NSLog by default

CocoaLumberjack dependency should be optional (via ifdefs) or removed altogether -- use NSLog by default. Most projects do not need CocoaLumberjack and would do fine just using NSLog logging by default. The extra dependency and classes are too custom/specific and unnecessarily complicate this project.

Snow Leopard Finder / connect to server gives out following...

Created a webdav server for the iPhone from the example and tried to connect and got the following message in the debug window.

Bonjour Service Published: domain(local.) type(_http._tcp.) name(iP4BK090565)
2012-02-15 19:38:49:869 iPhoneHTTPServer[47743:1c07] Unknown DAV property requested "quota-available-bytes"
2012-02-15 19:38:49:869 iPhoneHTTPServer[47743:1c07] Unknown DAV property requested "quota-used-bytes"
2012-02-15 19:38:49:869 iPhoneHTTPServer[47743:1c07] Unknown DAV property requested "quota"
2012-02-15 19:38:49:869 iPhoneHTTPServer[47743:1c07] Unknown DAV property requested "quotaused"
2012-02-15 19:38:50:276 iPhoneHTTPServer[47743:1c07] Unknown DAV property requested "appledoubleheader"
2012-02-15 19:38:50:386 iPhoneHTTPServer[47743:1c07] Unknown DAV property requested "appledoubleheader"
2012-02-15 19:38:50:483 iPhoneHTTPServer[47743:1c07] Unknown DAV property requested "appledoubleheader"
2012-02-15 19:38:50:540 iPhoneHTTPServer[47743:1b07] Unknown DAV property requested "appledoubleheader"
2012-02-15 19:41:46:342 iPhoneHTTPServer[47743:3d13] Unknown DAV property requested "appledoubleheader"

I am able to see the webdav volume from the finder. I am not able to delete files from the volume

Reproducible high latency after certain number of requests

I am using CocoaHTTPServer in my thesis project https://github.com/ArloL/IntAirAct. During a performance evaluation I noticed a weird behavior after a certain number of requests. To test this I created the project https://github.com/ArloL/HelloCocoaHTTPServer. I am using jMeter to test. The configuration can be found here https://github.com/ArloL/IntAirAct-Performance.

I tested three times with 100.000 requests on my MacBook Pro, 10.7.4 with 8 GB of RAM.
Test #1 has 6 requests that took about 20s each.
Test #2 has 6 requests that took about 20s each.
Test #3 has 6 requests that took about 8s each.

The interesting part is, is that the sample numbers of the long requests are nearly the same.
Test #1: 16374, 32747, 49123, 65498, 81873, 98252
Test #2: 16376, 32750, 49122, 65494, 81866, 98240
Test #3: 16364, 32704, 48976, 65223, 81537, 97824

As a control I tested with Sinatra and there I don't have these issues. All the numbers are close to multiples of 16384 (2^14). I would guess at a memory problem or something similar.

request timeout on SSL connection

Hi. I'm using a server in simple json exchange project. If i'm using isSecureServer, client start to produce timeouts:

2012-02-25 16:40:21.011 snowClientEnterprise[38925:7003] CLIENT CONTROLLER:>>>>>>> carrier start update:TWT S.p.A.
2012-02-25 16:41:27.951 snowClientEnterprise[38925:7003] CLIENT CONTROLLER: getJSON answer error download:The request timed out.
2012-02-25 16:41:27.952 snowClientEnterprise[38925:7003] CLIENT CONTROLLER: getJSON answer failed to decode answer with error:Reached the end of the buffer.

here is a client code to download:

NSString *jsonStringForReturn = [request JSONStringWithOptions:JKSerializeOptionNone serializeUnsupportedClassesUsingBlock:nil error:&error];
if (error) NSLog(@"CLIENT CONTROLLER: json decoding error:%@ in function:%@",[error localizedDescription],function);
NSData *bodyData = [jsonStringForReturn dataUsingEncoding:NSUTF8StringEncoding];
NSData *dataForBody = [[[NSData alloc] initWithData:bodyData] autorelease];
//NSLog(@"CLIENT CONTROLLER: string lenght is:%@ bytes",[NSNumber numberWithUnsignedInteger:[dataForBody length]]);
NSString *functionString = [NSString stringWithFormat:@"/%@",function];
NSURL *urlForRequest = [NSURL URLWithString:functionString relativeToURL:mainServer];
NSMutableURLRequest *requestToServer = [NSMutableURLRequest requestWithURL:urlForRequest];
[requestToServer setHTTPMethod:@"POST"];
[requestToServer setHTTPBody:dataForBody];
NSData *receivedResult = [NSURLConnection sendSynchronousRequest:requestToServer returningResponse:nil error:&error];

if (error) NSLog(@"CLIENT CONTROLLER: getJSON answer error download:%@",[error localizedDescription]);
NSString *answer = [[NSString alloc] initWithData:receivedResult encoding:NSUTF8StringEncoding];
JSONDecoder *jkitDecoder = [JSONDecoder decoder];
NSDictionary *finalResult = [jkitDecoder objectWithUTF8String:(const unsigned char *)[answer UTF8String] length:[answer length] error:&error];
[answer release];

if (error) NSLog(@"CLIENT CONTROLLER: getJSON answer failed to decode answer with error:%@",[error localizedDescription]);

when ssl disabled, all working fine for same code.
here is myHTTPclass config:

  • (BOOL)isPasswordProtected:(NSString *)path
    {
    // We're only going to password protect the "secret" directory.

    BOOL result = [path hasPrefix:@"/"];

    HTTPLogTrace2(@"%@[%p]: isPasswordProtected(%@) - %@", THIS_FILE, self, path, (result ? @"YES" : @"NO"));

    return NO;
    }
    //
    //- (BOOL)useDigestAccessAuthentication
    //{
    // HTTPLogTrace();
    //
    // // Digest access authentication is the default setting.
    // // Notice in Safari that when you're prompted for your password,
    // // Safari tells you "Your login information will be sent securely."
    // //
    // // If you return NO in this method, the HTTP server will use
    // // basic authentication. Try it and you'll see that Safari
    // // will tell you "Your password will be sent unencrypted",
    // // which is strongly discouraged.
    //
    // return YES;
    //}
    //

  • (NSString *)passwordForUser:(NSString *)username
    {
    HTTPLogTrace();

    // You can do all kinds of cool stuff here.
    // For simplicity, we're not going to check the username, only the password.
    if ([username isEqualToString:@"xxx"]) return @"xxx
    else return [NSString stringWithFormat:@"%@",[NSNumber numberWithInt:arc4random() % 1000000000000000000]];

}
//

  • (BOOL)isSecureServer
    {
    HTTPLogTrace();

    // Create an HTTPS server (all connections will be secured via SSL/TLS)
    return NO;
    }
    //

  • (NSArray *)sslIdentityAndCertificates
    {
    HTTPLogTrace();

    NSArray *result = [DDKeychain SSLIdentityAndCertificates];
    if([result count] == 0)
    {
    [DDKeychain createNewIdentity];
    return [DDKeychain SSLIdentityAndCertificates];
    }
    return result;
    }

HTTPSERVER.m bug

The accessor function should return result, not name on line 288.

Function definition won't do anything

HTTPConnection.m, line 2496.

The following function won't do anything:

  • (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err;
    {
    ...
    }

I think the semi-colon at the end of the function parameter list shouldn't be there.

WEBDAV uploads

WEBDAV uploads do not work properly. I am using Mac OS X Finder as the client and the WebDavServer example running on iOS simulator with no changes.

1 - After a small file upload, the uploaded file appears listed but it results in an empty file.

2 - For larger files the WEBDAV server crashes at
NSAssert(requestContentStream == nil, @"requestContentStream should be nil");

Are Uploads properly supported ?

Is there anything I need to know to make it work?

Thanks.

Joan Lluch

HTTPProxyResponse

Hello Robbiehanson,

To start, I am really really new to IOS / Objective C.

I am given a project which already uses your server. The enhancement needed to decrypt a progressive download video. In my research a couple of people have asked you and implemented this, but I could not find any code.

So I went on and mucked HTTPAsyncFileResponse myself. Now while waiting for my hairs to grow back, the code works fine. At this state (my knowledge about the language and framework is almost nil) I am satisfied with this code.

This code is for anyone who don't want to start clean. and over the top of your head if anyone see any big issues/leaks please comment.

HTTPConnection.m

- (void)sendResponseHeadersAndBody
{
...
        if ([ranges count] == 1)
        {
            if(remote){
            HTTPProxyResponse * proxyResponse = (HTTPProxyResponse *)httpResponse;
            response = [proxyResponse remoteResponse];
            } 
            else 
            {
            response = [self newUniRangeResponse:contentLength];
            }
        }
        else
        {
            response = [self newMultiRangeResponse:contentLength];
        }
...
}

HTTPProxyResponse.h

#import <Foundation/Foundation.h>
#import "HTTPConnection.h"
#import "HTTPResponse.h"
#import "HTTPMessage.h"
#import "GCDAsyncSocket.h"

@class HTTPConnection;
@class GCDAsyncSocket;

@interface HTTPProxyResponse : NSObject <HTTPResponse>
{
    dispatch_queue_t socketQueue;
    GCDAsyncSocket *asyncSocket;

    HTTPMessage *localRequest;
    HTTPMessage __strong *remoteResponse;
    unsigned int numHeaderLines;

    HTTPConnection *connection;

    UInt64 fileLength;  // Actual lwngth of the file
    UInt64 fileOffset;  // File offset as pertains to data given to connection
    UInt64 readOffset;  // File offset as pertains to data read from file (but maybe not returned to connection)

    BOOL connected;
    BOOL aborted;

    NSMutableData __strong *buffer;
    NSData __strong *data;

    void *readBuffer;
    NSUInteger readBufferSize;     // Malloced size of readBuffer
    NSUInteger readBufferOffset;   // Offset within readBuffer where the end of existing data is
    NSUInteger readRequestLength;
}

@property (nonatomic, strong) HTTPMessage *remoteResponse;

- (id)initWithLocalRequest:(HTTPMessage *)request forConnection:(HTTPConnection *)connection;

@end

HTTPProxyResponse.m

#import "HTTPProxyResponse.h"
#import "MyAppDelegate.h"
#import "HTTPLogging.h"

#import <unistd.h>
#import <fcntl.h>

#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonDigest.h>

// Log levels : off, error, warn, info, verbose
// Other flags: trace
static const int httpLogLevel = HTTP_LOG_FLAG_TRACE;

// Define chunk size used to read in data for responses
// This is how much data will be read from disk into RAM at a time
#if TARGET_OS_IPHONE
    #define READ_CHUNKSIZE  (1024 * 128)
#else
    #define READ_CHUNKSIZE  (1024 * 512)
#endif

// Define the various timeouts (in seconds) for various parts of the HTTP process
#define TIMEOUT_READ_FIRST_HEADER_LINE       30
#define TIMEOUT_READ_SUBSEQUENT_HEADER_LINE  30
#define TIMEOUT_READ_BODY                    -1
#define TIMEOUT_WRITE_HEAD                   30
#define TIMEOUT_WRITE_ERROR                  30

// Define the various limits
// LIMIT_MAX_HEADER_LINE_LENGTH: Max length (in bytes) of any single line in a header (including \r\n)
// LIMIT_MAX_HEADER_LINES      : Max number of lines in a single header (including first GET line)
#define LIMIT_MAX_HEADER_LINE_LENGTH  8190
#define LIMIT_MAX_HEADER_LINES         100

// Define the various tags we'll use to differentiate what it is we're currently doing
#define HTTP_REQUEST_HEADER                10

#define HTTP_RESPONSE_HEADER                 92
#define HTTP_RESPONSE_BODY                   93
#define HTTP_FINAL_RESPONSE                  91

@implementation HTTPProxyResponse

@synthesize remoteResponse;

- (NSURL *)remoteRequestURI
{
    return [[NSURL alloc] initWithString:@"http://www.example.com/path/to/my/video.mp4"];
}

- (id)initWithLocalRequest:(HTTPMessage *)request forConnection:(HTTPConnection *)parent
{
    if ((self = [super init]))
    {
        HTTPLogTrace();

        connection = parent; // Parents retain children, children do NOT retain parents
        localRequest = request;

        NSURL *remoteURI = [self remoteRequestURI];

        MyAppDelegate * appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
        fileLength = [appDelegate currentVideoLength];

        fileOffset = 0;

        socketQueue = dispatch_queue_create("AsyncSocket", NULL);
        asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:socketQueue];

        uint16_t port = [[remoteURI port] unsignedLongLongValue];
        if(port==0) port = 80;

        NSError *error = nil;
        bool res = [asyncSocket connectToHost:[remoteURI host] onPort:port error:&error];
        if(!res || error) return nil;

        connected = NO;
        aborted = NO;
    }
    return self;
}

- (void)abort
{
    HTTPLogTrace();
    [asyncSocket disconnect];
    [connection responseDidAbort:self];
    aborted = YES;
}

- (BOOL)delayResponseHeaders
{
    return !(connected && [remoteResponse isHeaderComplete]);
}

- (void)processReadBuffer:(int)read
{
    // This method is here to allow superclasses to perform post-processing of the data.
    // For an example, see the HTTPDynamicFileResponse class.
    //
    // At this point, the readBuffer has readBufferOffset bytes available.
    // This method is in charge of updating the readBufferOffset.
    // Failure to do so will cause the readBuffer to grow to fileLength. (Imagine a 1 GB file...)

    // Copy the data out of the temporary readBuffer.
    data = [[NSData alloc] initWithBytes:readBuffer length:readBufferOffset];

    // Reset the read buffer.
    readBufferOffset = 0;

    // Notify the connection that we have data available for it.
    [connection responseHasAvailableData:self];
}


- (BOOL)canContinue
{
    if (aborted || asyncSocket == nil || [remoteResponse statusCode] == 304)
    {
        return NO;
    }
    return [asyncSocket isConnected];
}

- (UInt64)contentLength
{
    HTTPLogTrace2(@"%@[%p]: contentLength - %llu", THIS_FILE, self, fileLength);
    return fileLength;
}

- (UInt64)offset
{
    HTTPLogTrace();
    return fileOffset;
}

- (void)setOffset:(UInt64)offset
{
    HTTPLogTrace2(@"%@[%p]: setOffset:%llu", THIS_FILE, self, offset);
    fileOffset = offset;
    readOffset = offset;
}


- (void)startHeadRequest
{
    HTTPLogTrace();

    NSURL *remoteUrl = [self remoteRequestURI];

    HTTPMessage *remoteRequest = [[HTTPMessage alloc] initRequestWithMethod:@"HEAD" URL:remoteUrl version:HTTPVersion1_1];
    // Add HOST headers¸
    [remoteRequest setHeaderField:@"HOST" value:[remoteUrl host]];
    [remoteRequest setHeaderField:@"User-Agent" value:[localRequest headerField:@"User-Agent"]];
    [remoteRequest setHeaderField:@"Range" value:[NSString stringWithFormat:@"%lld-",fileOffset]];
    [remoteRequest setHeaderField:@"Connection" value:@"Keep-Alive"];

    NSData *requestData = [remoteRequest messageData];
    [asyncSocket writeData:requestData withTimeout:TIMEOUT_WRITE_HEAD tag:HTTP_REQUEST_HEADER];
}
- (void)startContentRequest
{
    HTTPLogTrace();

    NSURL *remoteUrl = [self remoteRequestURI];

    HTTPMessage *remoteRequest = [[HTTPMessage alloc] initRequestWithMethod:[localRequest method] URL:remoteUrl version:HTTPVersion1_1];
    // Add HOST headers¸
    [remoteRequest setHeaderField:@"HOST" value:[remoteUrl host]];

    // Add standart headers from orignal request
    NSMutableDictionary *requestHeaders = [[localRequest allHeaderFields] mutableCopy];
    [requestHeaders removeObjectForKey:@"HOST"];

    NSEnumerator *keyEnumerator = [requestHeaders keyEnumerator];
    NSString *key;

    while ((key = [keyEnumerator nextObject]))
    {
        NSString *value = [requestHeaders objectForKey:key];
        [remoteRequest setHeaderField:key value:value];
    }

    NSData *requestData = [remoteRequest messageData];
    [asyncSocket writeData:requestData withTimeout:TIMEOUT_WRITE_HEAD tag:HTTP_REQUEST_HEADER];
}
- (NSData *)readDataOfLength:(NSUInteger)length
{
    if (data)
    {
        NSUInteger dataLength = [data length];
        fileOffset += dataLength;
        NSData *result = data;
        data = nil;
        return result;
    }
    else
    {
        if(!connected){
            return nil;
        }
        if (![self canContinue])
        {
            [self abort];
            return nil;
        }
        HTTPLogVerbose(@"%@[%p]: Reading data of length %d", THIS_FILE, self, length);
        [asyncSocket readDataToLength:length withTimeout:TIMEOUT_READ_BODY buffer:buffer bufferOffset:readBufferOffset tag:HTTP_RESPONSE_BODY];
        return nil;
    }
}

- (BOOL)isDone
{
    BOOL result = (fileOffset == fileLength);
    HTTPLogTrace2(@"%@[%p]: isDone - %@", THIS_FILE, self, (result ? @"YES" : @"NO"));
    return result;
}

- (BOOL)isAsynchronous
{
    HTTPLogTrace();
    return YES;
}

- (void)connectionDidClose
{
    HTTPLogTrace();
    [asyncSocket  disconnect];
}


- (void)dealloc
{
    HTTPLogTrace();
    //if (readBuffer)
    //  free(readBuffer);
    if(socketQueue)
        dispatch_release(socketQueue);
    //[super dealloc];
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark GCDAsyncSocket Delegate
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
    connected = true;
    if(fileLength >0)
    {
        [self startContentRequest];
    } else {
        [self startHeadRequest];
    }
}
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    connected = false;
    if(err) {
        HTTPLogTrace2(@"%@[%p]: socketDidDisconnect:\n %@", THIS_FILE, self, err);
    }
}
/**
 * This method is called after the socket has successfully written data to the stream.
 **/
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    if (tag == HTTP_REQUEST_HEADER)
    {
        remoteResponse = [[HTTPMessage alloc] initEmptyResponse];

        [asyncSocket readDataToData:[GCDAsyncSocket CRLFData]
                        withTimeout:TIMEOUT_READ_FIRST_HEADER_LINE
                          maxLength:LIMIT_MAX_HEADER_LINE_LENGTH
                                tag:HTTP_RESPONSE_HEADER];
    }
}
/**
 * This method is called after the socket has successfully read data from the stream.
 * Remember that this method will only be called after the socket reaches a CRLF, or after it's read the proper length.
 **/
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData*)dat withTag:(long)tag
{
    if (tag == HTTP_RESPONSE_HEADER)
    {
        NSString *log = [[NSString alloc]initWithData:dat encoding:NSUTF8StringEncoding];
        HTTPLogTrace2(@"%@[%p]: didReadData\n %@", THIS_FILE, self, log);

        // Append the header line to the http message
        BOOL result = [remoteResponse appendData:dat];

        if (!result)
        {
            HTTPLogWarn(@"%@[%p]: Malformed request", THIS_FILE, self);
            [self abort];
        }
        else if (![remoteResponse isHeaderComplete])
        {
            // We don't have a complete header yet
            // That is, we haven't yet received a CRLF on a line by itself, indicating the end of the header
            if (++numHeaderLines > LIMIT_MAX_HEADER_LINES)
            {
                // Reached the maximum amount of header lines in a single HTTP request
                // This could be an attempted DOS attack
                [self abort];

                // Explictly return to ensure we don't do anything after the socket disconnect
                return;
            }
            else
            {
                [asyncSocket readDataToData:[GCDAsyncSocket CRLFData]
                                withTimeout:TIMEOUT_READ_SUBSEQUENT_HEADER_LINE
                                  maxLength:LIMIT_MAX_HEADER_LINE_LENGTH
                                        tag:HTTP_RESPONSE_HEADER];
            }
        }
        else 
        {
            // We have an entire HTTP request header from the client

            //NSRange isHeadRequest = [[remoteResponse method] rangeOfString:@"HEAD" options:NSCaseInsensitiveSearch];
            //if(isHeadRequest.location == NSNotFound)
            if(fileLength > 0)
            {
                // Now we need to reply to the local request
                // Not able to pass my buffer dont know why
                //buffer = [[NSMutableData alloc] initWithCapacity:READ_CHUNKSIZE];
                //Kick start reading the body from the connections getDataOfLength
                [connection responseHasAvailableData:self];
            }
            else
            {
                NSString *fLength = [remoteResponse headerField:@"Content-Length"];
                fileLength = [fLength longLongValue];
                if(fileLength > 0)
                {
                    MyAppDelegate * appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
                    appDelegate.currentVideoLength = fileLength;

                    [self startContentRequest];
                }
                else
                {
                    [self abort];
                }
            }
        }
    }
    else if (tag == HTTP_RESPONSE_BODY)
    {
        // Handle a chunk of data from the remote response body
        NSUInteger read = [dat length];
        readBuffer = (void *)[dat bytes];
        readOffset += read;
        readBufferOffset += read;

        [self processReadBuffer:read];
    }
}

@end

iOS server socket dies on screen lock

It seems the server socket is dying when a device with iOS 5+ goes to sleep. This is easily reproducible with the iPhoneHTTPServer project. Just run it with the default configuration (connected to a WiFi network to verify that the server is reachable), then lock the device (the app can be in the foreground or in the background, doesn't matter) and unlock it again. Try to connect to the web server and the connection will be refused.

CRASH: dispatch_source_cancel(readSource) - message sent to deallocated instance

HTTPAsyncFileResponse.m:126
dispatch_source_cancel(readSource);

(lldb) po readSource
2013-08-01 21:04:23.650 SOHUVideo[8379:11a27] *** -[OS_dispatch_source respondsToSelector:]: message sent to deallocated instance 0x1a8cc020
$1 = 0x1a8cc020 [no Objective-C description available]

Thread 18, Queue : HTTPAsyncFileResponse
#0 0x3b6f97f0 in _os_object_retain_internal$VARIANT$mp ()
#1 0x3b6f9d8a in dispatch_source_cancel$VARIANT$mp ()
#2 0x00686286 in -[HTTPAsyncFileResponse cancelReadSource] at /Users/iwill/SOHU/svn/src/trunk/modules/Utility/Classes/HTTPServer/CocoaHTTPServer/Responses/HTTPAsyncFileResponse.m:126
#3 0x00687452 in _43-[HTTPAsyncFileResponse connectionDidClose]block_invoke at /Users/iwill/SOHU/svn/src/trunk/modules/Utility/Classes/HTTPServer/CocoaHTTPServer/Responses/HTTPAsyncFileResponse.m:388
#4 0x3b6f7572 in dispatch_barrier_sync_f_invoke ()
#5 0x006873f4 in -[HTTPAsyncFileResponse connectionDidClose] at /Users/iwill/SOHU/svn/src/trunk/modules/Utility/Classes/HTTPServer/CocoaHTTPServer/Responses/HTTPAsyncFileResponse.m:379
#6 0x30d34874 in **invoking
** ()
#7 0x30c81f4a in -NSInvocation invoke
#8 0x30c81ab2 in -NSInvocation invokeWithTarget:
#9 0x006abebe in -[HTTPResponseProxy forwardInvocation:] at /Users/iwill/SOHU/svn/src/trunk/modules/Utility/Classes/HTTPServer/RoutingHTTPServer/HTTPResponseProxy.m:68
#10 0x30d333e0 in _forwarding
()
#11 0x30c80f88 in **forwarding_prep_0
** ()
#12 0x0067ba50 in -[HTTPConnection die] at /Users/iwill/SOHU/svn/src/trunk/modules/Utility/Classes/HTTPServer/CocoaHTTPServer/HTTPConnection.m:2654
#13 0x0067af7c in -[HTTPConnection socketDidDisconnect:withError:] at /Users/iwill/SOHU/svn/src/trunk/modules/Utility/Classes/HTTPServer/CocoaHTTPServer/HTTPConnection.m:2491
#14 0x00698024 in __33-[GCDAsyncSocket closeWithError:]_block_invoke at /Users/iwill/SOHU/svn/src/trunk/modules/Utility/Classes/HTTPServer/GCDAsyncSocket/GCDAsyncSocket.m:2809
#15 0x3b6f382a in _dispatch_call_block_and_release ()
#16 0x3b6f7032 in _dispatch_async_redirect_invoke$VARIANT$mp ()
#17 0x3b6f86ec in _dispatch_root_queue_drain ()
#18 0x3b6f88d4 in _dispatch_worker_thread2 ()
#19 0x3b83646e in _pthread_wqthread ()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.