mactransportagent.cpp

来自「funambol window mobile客户端源代码」· C++ 代码 · 共 259 行

CPP
259
字号
/*
 * Funambol is a mobile platform developed by Funambol, Inc. 
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission 
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE 
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Affero General Public License 
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 * 
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite 
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 * 
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 * 
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably 
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */


#include "base/fscapi.h"

#if FUN_TRANSPORT_AGENT == FUN_MAC_TRANSPORT_AGENT

#include <CoreFoundation/CoreFoundation.h>

#if defined(FUN_IPHONE)
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCNetworkReachability.h>
#if TARGET_IPHONE_SIMULATOR
#include <CoreServices/CoreServices.h>
#else
#include <CFNetwork/CFNetwork.h>
#endif
#else
#include <CoreServices/CoreServices.h>
#endif

#include "http/MacTransportAgent.h"
#include "http/constants.h"

#include "base/util/utils.h"
#include "base/util/StringBuffer.h"


USE_NAMESPACE

MacTransportAgent::MacTransportAgent() : TransportAgent() {}

MacTransportAgent::~MacTransportAgent() {}

/*
 * Constructor.
 * In this implementation newProxy is ignored, since proxy configuration
 * is taken from the WinInet subsystem.
 *
 * @param url the url where messages will be sent with sendMessage()
 * @param proxy proxy information or NULL if no proxy should be used
 */
MacTransportAgent::MacTransportAgent(URL& newURL, Proxy& newProxy, unsigned int maxResponseTimeout)
: TransportAgent(newURL, newProxy, maxResponseTimeout)
{
    
}
    

/*
 * Sends the given SyncML message to the server specified
 * by the instal property 'url'. Returns the response status code or -1
 * if it was not possible initialize the connection.
 *
 * Use getResponse() to get the server response.
 */
char* MacTransportAgent::sendMessage(const char* msg){

    if(!msg) {
        LOG.error("MacTransportAgent::sendMessage error: NULL message.");
        setError(ERR_NETWORK_INIT, "MacTransportAgent::sendMessage error: NULL message.");
        return NULL;
    }
   
    bool gotflags = true;
    bool isReachable = true;
    bool noConnectionRequired = true; 

#if defined(FUN_IPHONE)    
    SCNetworkReachabilityFlags        flags;
    SCNetworkReachabilityRef scnReachRef = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, url.host);
    
    gotflags = SCNetworkReachabilityGetFlags(scnReachRef, &flags);
    isReachable = flags & kSCNetworkReachabilityFlagsReachable;
    noConnectionRequired = !(flags & kSCNetworkReachabilityFlagsConnectionRequired);
    if ((flags & kSCNetworkReachabilityFlagsIsWWAN)) {
        noConnectionRequired = true;
    }
#endif
    

    if ( gotflags && isReachable && noConnectionRequired ){
        
        // size_t size = strlen(msg);
        LOG.debug("Requesting resource %s at %s:%d", url.resource, url.host, url.port);
        
        LOG.debug("Sending HTTP Request: %s", msg);
        
        // Construct some headers
        CFStringRef headerFieldName = CFSTR("Content-Type");
        CFStringRef headerFieldValue = CFSTR("application/vnd.syncml+xml");
        
        // Construct URL
        CFStringRef CFurl =  CFStringCreateWithCString(NULL, url.fullURL, kCFStringEncodingUTF8);
        CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, CFurl, NULL);
        
        CFStringRef requestMethod = CFSTR("POST");
        
        CFHTTPMessageRef httpRequest =
        CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
        CFStringRef useragent = CFStringCreateWithCString(NULL, getUserAgent(), kCFStringEncodingUTF8);
        CFHTTPMessageSetHeaderFieldValue(httpRequest, CFSTR("user-agent"),  useragent);
        if(!httpRequest){
            LOG.error("MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");
            setError(ERR_NETWORK_INIT, "MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");
            return NULL;
        }
        
        CFDataRef bodyData = CFDataCreate(kCFAllocatorDefault, (const UInt8*)msg, strlen(msg));	
        if (!bodyData){
            LOG.error("MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");
            setError(ERR_NETWORK_INIT, "MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");
            return NULL;
        }        
        CFHTTPMessageSetBody(httpRequest, bodyData);
        CFHTTPMessageSetHeaderFieldValue(httpRequest, headerFieldName, headerFieldValue);
        
        CFReadStreamRef responseStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, httpRequest);
        if (!CFReadStreamOpen(responseStream)) {//Sends request
            LOG.error("Failed to send HTTP request...");
        }
        
        StringBuffer result;
        
#define READ_SIZE 1000
        CFIndex bytesRead = 1;
        UInt8   buffer[READ_SIZE];
        while ( (bytesRead = CFReadStreamRead(responseStream, buffer, READ_SIZE-1)) > 0)
        {
            //   Convert what was read to a C-string
            buffer[bytesRead] = 0;
            //   Append it to the reply string
            result.append((const char*)buffer);
        }
        
        int statusCode = -1;
        CFHTTPMessageRef reply = (CFHTTPMessageRef) CFReadStreamCopyProperty( responseStream, kCFStreamPropertyHTTPResponseHeader);
        
        
        // Pull the status code from the headers
        if (reply) {
            statusCode = CFHTTPMessageGetResponseStatusCode(reply);
            CFRelease(reply);
        }
        
        
        LOG.debug("Status Code: %d", statusCode);
        LOG.debug("Result: %s", result.c_str());
        
        char* ret=0;
        
        switch (statusCode) {
            case 0: {
                LOG.debug("Http request successful.");
                
                // No errors, copy the response
                // TODO: avoid byte copy
                ret = stringdup(result.c_str());
                
                break;
            }
            case 200: {
                LOG.debug("Http request successful.");
                
                // No errors, copy the response
                // TODO: avoid byte copy
                ret = stringdup(result.c_str());
                
                break;
            }
            case -1: {                    // no connection (TODO: implement retry)
                setErrorF(ERR_SERVER_ERROR, "Network error in server receiving data. ");
                LOG.error("%s", getLastErrorMsg());
                
                break;
            }
            case 400: {                    // 400 bad request error. TODO: retry to send the message
                setErrorF(ERR_SERVER_ERROR, "HTTP server error: %d. Server failure.", statusCode);
                LOG.debug("%s", getLastErrorMsg());
                
                break;
            }
            case 500: {     // 500 -> out code 2052
                setErrorF(ERR_SERVER_ERROR, "HTTP server error: %d. Server failure.", statusCode);
                LOG.debug("%s", getLastErrorMsg());
                break;
            }
            case 404: {         // 404 -> out code 2060
                setErrorF(ERR_HTTP_NOT_FOUND, "HTTP request error: resource not found (status %d)", statusCode);
                LOG.debug("%s", getLastErrorMsg());
                break;
            }
            case 408: {   // 408 -> out code 2061
                setErrorF(ERR_HTTP_REQUEST_TIMEOUT, "HTTP request error: server timed out waiting for request (status %d)", statusCode);
                LOG.debug("%s", getLastErrorMsg());
                break;
            }
                
            default: {
                setErrorF(statusCode, "HTTP request error: status received = %d", statusCode);
                LOG.error("%s", getLastErrorMsg());
            }
        }
        
        CFRelease(headerFieldName);
        CFRelease(headerFieldValue);
        CFRelease(CFurl);
        CFRelease(myURL);
        CFRelease(httpRequest);
        CFRelease(bodyData);
        CFRelease(responseStream);
        CFRelease(requestMethod);

        
        return ret;
    }else{
        setErrorF(ERR_CONNECT, "Network error: the attempt to connect to the server failed -> exit");
        LOG.debug("%s", getLastErrorMsg());
        
        return NULL;
    }
}

#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?