16f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber/*
26f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber * Copyright 2012, The Android Open Source Project
36f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber *
46f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
56f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber * you may not use this file except in compliance with the License.
66f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber * You may obtain a copy of the License at
76f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber *
86f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
96f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber *
106f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber * Unless required by applicable law or agreed to in writing, software
116f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
126f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber * See the License for the specific language governing permissions and
146f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber * limitations under the License.
156f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber */
166f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
176f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber//#define LOG_NDEBUG 0
186f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#define LOG_TAG "NetworkSession"
196f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include <utils/Log.h>
206f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
216f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include "ANetworkSession.h"
226f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include "ParsedMessage.h"
236f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
246f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include <arpa/inet.h>
256f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include <fcntl.h>
2643433111d4adff6a138447dfadf531046497a008Andreas Huber#include <linux/tcp.h>
276f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include <net/if.h>
286f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include <netdb.h>
296f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include <netinet/in.h>
309dffd24e00a1b2abd5e2dcc2366c0327ec3701b8Andreas Huber#include <sys/ioctl.h>
316f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include <sys/socket.h>
326f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
336f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include <media/stagefright/foundation/ABuffer.h>
346f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include <media/stagefright/foundation/ADebug.h>
356f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include <media/stagefright/foundation/AMessage.h>
366f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#include <media/stagefright/foundation/hexdump.h>
376f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
386f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Hubernamespace android {
396f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
408060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huberstatic uint16_t U16_AT(const uint8_t *ptr) {
418060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    return ptr[0] << 8 | ptr[1];
428060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber}
438060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
448060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huberstatic uint32_t U32_AT(const uint8_t *ptr) {
458060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
468060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber}
478060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
488060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huberstatic uint64_t U64_AT(const uint8_t *ptr) {
498060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    return ((uint64_t)U32_AT(ptr)) << 32 | U32_AT(ptr + 4);
508060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber}
518060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
526f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatic const size_t kMaxUDPSize = 1500;
5399f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhangstatic const int32_t kMaxUDPRetries = 200;
546f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstruct ANetworkSession::NetworkThread : public Thread {
566f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    NetworkThread(ANetworkSession *session);
576f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
586f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberprotected:
596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    virtual ~NetworkThread();
606f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
616f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberprivate:
626f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    ANetworkSession *mSession;
636f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
646f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    virtual bool threadLoop();
656f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
666f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    DISALLOW_EVIL_CONSTRUCTORS(NetworkThread);
676f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber};
686f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
696f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstruct ANetworkSession::Session : public RefBase {
708060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    enum Mode {
718060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        MODE_RTSP,
728060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        MODE_DATAGRAM,
738060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        MODE_WEBSOCKET,
748060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    };
758060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    enum State {
776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        CONNECTING,
786f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        CONNECTED,
797d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        LISTENING_RTSP,
807d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        LISTENING_TCP_DGRAMS,
816f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        DATAGRAM,
826f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    };
836f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
846f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    Session(int32_t sessionID,
856f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            State state,
866f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            int s,
876f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            const sp<AMessage> &notify);
886f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
896f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    int32_t sessionID() const;
906f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    int socket() const;
916f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    sp<AMessage> getNotificationMessage() const;
926f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
937d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    bool isRTSPServer() const;
947d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    bool isTCPDatagramServer() const;
956f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
966f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    bool wantsToRead();
976f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    bool wantsToWrite();
986f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
996f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    status_t readMore();
1006f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    status_t writeMore();
1016f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
102632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    status_t sendRequest(
103632177b7446185a0407b7df96f684a9b8b980765Andreas Huber            const void *data, ssize_t size, bool timeValid, int64_t timeUs);
1046f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1058060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    void setMode(Mode mode);
1068060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
1078060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    status_t switchToWebSocketMode();
1087d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
1096f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberprotected:
1106f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    virtual ~Session();
1116f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1126f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberprivate:
113632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    enum {
114632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        FRAGMENT_FLAG_TIME_VALID = 1,
115632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    };
116632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    struct Fragment {
117632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        uint32_t mFlags;
118632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        int64_t mTimeUs;
119632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        sp<ABuffer> mBuffer;
120632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    };
121632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
1226f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    int32_t mSessionID;
1236f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    State mState;
1248060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    Mode mMode;
1256f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    int mSocket;
1266f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    sp<AMessage> mNotify;
1276f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    bool mSawReceiveFailure, mSawSendFailure;
12899f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang    int32_t mUDPRetries;
1296f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
130632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    List<Fragment> mOutFragments;
1316f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1326f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    AString mInBuffer;
1336f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
134e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber    int64_t mLastStallReportUs;
135e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber
1366f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    void notifyError(bool send, status_t err, const char *detail);
1376f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    void notify(NotificationReason reason);
1386f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
139632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    void dumpFragmentStats(const Fragment &frag);
140632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
1416f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    DISALLOW_EVIL_CONSTRUCTORS(Session);
1426f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber};
1436f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber////////////////////////////////////////////////////////////////////////////////
1446f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1456f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas HuberANetworkSession::NetworkThread::NetworkThread(ANetworkSession *session)
1466f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    : mSession(session) {
1476f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
1486f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1496f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas HuberANetworkSession::NetworkThread::~NetworkThread() {
1506f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
1516f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1526f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberbool ANetworkSession::NetworkThread::threadLoop() {
1536f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    mSession->threadLoop();
1546f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return true;
1566f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
1576f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1586f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber////////////////////////////////////////////////////////////////////////////////
1596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1606f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas HuberANetworkSession::Session::Session(
1616f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        int32_t sessionID,
1626f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        State state,
1636f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        int s,
1646f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        const sp<AMessage> &notify)
1656f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    : mSessionID(sessionID),
1666f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber      mState(state),
1678060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber      mMode(MODE_DATAGRAM),
1686f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber      mSocket(s),
1696f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber      mNotify(notify),
1706f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber      mSawReceiveFailure(false),
171e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber      mSawSendFailure(false),
17299f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang      mUDPRetries(kMaxUDPRetries),
173e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber      mLastStallReportUs(-1ll) {
1746f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (mState == CONNECTED) {
1756f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        struct sockaddr_in localAddr;
1766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        socklen_t localAddrLen = sizeof(localAddr);
1776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1786f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        int res = getsockname(
1796f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                mSocket, (struct sockaddr *)&localAddr, &localAddrLen);
1806f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        CHECK_GE(res, 0);
1816f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1826f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        struct sockaddr_in remoteAddr;
1836f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        socklen_t remoteAddrLen = sizeof(remoteAddr);
1846f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1856f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        res = getpeername(
1866f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                mSocket, (struct sockaddr *)&remoteAddr, &remoteAddrLen);
1876f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        CHECK_GE(res, 0);
1886f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1896f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        in_addr_t addr = ntohl(localAddr.sin_addr.s_addr);
1906f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        AString localAddrString = StringPrintf(
1916f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                "%d.%d.%d.%d",
1926f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                (addr >> 24),
1936f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                (addr >> 16) & 0xff,
1946f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                (addr >> 8) & 0xff,
1956f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                addr & 0xff);
1966f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1976f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        addr = ntohl(remoteAddr.sin_addr.s_addr);
1986f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        AString remoteAddrString = StringPrintf(
1996f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                "%d.%d.%d.%d",
2006f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                (addr >> 24),
2016f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                (addr >> 16) & 0xff,
2026f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                (addr >> 8) & 0xff,
2036f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                addr & 0xff);
2046f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2056f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        sp<AMessage> msg = mNotify->dup();
2066f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        msg->setInt32("sessionID", mSessionID);
2076f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        msg->setInt32("reason", kWhatClientConnected);
2086f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        msg->setString("server-ip", localAddrString.c_str());
2096f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        msg->setInt32("server-port", ntohs(localAddr.sin_port));
2106f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        msg->setString("client-ip", remoteAddrString.c_str());
2116f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        msg->setInt32("client-port", ntohs(remoteAddr.sin_port));
2126f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        msg->post();
2136f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
2146f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
2156f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2166f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas HuberANetworkSession::Session::~Session() {
217a7f7e0ac9436a8417bb9f31aecedfec1909d4630Andreas Huber    ALOGV("Session %d gone", mSessionID);
2186f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2196f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    close(mSocket);
2206f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    mSocket = -1;
2216f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
2226f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2236f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberint32_t ANetworkSession::Session::sessionID() const {
2246f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return mSessionID;
2256f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
2266f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2276f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberint ANetworkSession::Session::socket() const {
2286f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return mSocket;
2296f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
2306f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2318060060217ff16cd67c8f6a15c649f44c343acf0Andreas Hubervoid ANetworkSession::Session::setMode(Mode mode) {
2328060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    mMode = mode;
2338060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber}
2348060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
2358060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huberstatus_t ANetworkSession::Session::switchToWebSocketMode() {
2368060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    if (mState != CONNECTED || mMode != MODE_RTSP) {
2378060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        return INVALID_OPERATION;
2388060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    }
2398060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
2408060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    mMode = MODE_WEBSOCKET;
2418060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
2428060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    return OK;
2437d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber}
2447d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
2456f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Hubersp<AMessage> ANetworkSession::Session::getNotificationMessage() const {
2466f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return mNotify;
2476f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
2486f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2497d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huberbool ANetworkSession::Session::isRTSPServer() const {
2507d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    return mState == LISTENING_RTSP;
2517d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber}
2527d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
2537d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huberbool ANetworkSession::Session::isTCPDatagramServer() const {
2547d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    return mState == LISTENING_TCP_DGRAMS;
2556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
2566f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2576f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberbool ANetworkSession::Session::wantsToRead() {
2586f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return !mSawReceiveFailure && mState != CONNECTING;
2596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
2606f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2616f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberbool ANetworkSession::Session::wantsToWrite() {
2626f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return !mSawSendFailure
2636f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        && (mState == CONNECTING
264632177b7446185a0407b7df96f684a9b8b980765Andreas Huber            || (mState == CONNECTED && !mOutFragments.empty())
265632177b7446185a0407b7df96f684a9b8b980765Andreas Huber            || (mState == DATAGRAM && !mOutFragments.empty()));
2666f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
2676f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2686f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::Session::readMore() {
2696f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (mState == DATAGRAM) {
2708060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        CHECK_EQ(mMode, MODE_DATAGRAM);
2718060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
2726f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        status_t err;
2736f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        do {
2746f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            sp<ABuffer> buf = new ABuffer(kMaxUDPSize);
2756f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            struct sockaddr_in remoteAddr;
2776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            socklen_t remoteAddrLen = sizeof(remoteAddr);
2786f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2796f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            ssize_t n;
2806f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            do {
2816f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                n = recvfrom(
2826f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                        mSocket, buf->data(), buf->capacity(), 0,
2836f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                        (struct sockaddr *)&remoteAddr, &remoteAddrLen);
2846f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            } while (n < 0 && errno == EINTR);
2856f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2866f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            err = OK;
2876f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            if (n < 0) {
2886f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                err = -errno;
2896f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            } else if (n == 0) {
2906f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                err = -ECONNRESET;
2916f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            } else {
2926f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                buf->setRange(0, n);
2936f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2946f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                int64_t nowUs = ALooper::GetNowUs();
2956f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                buf->meta()->setInt64("arrivalTimeUs", nowUs);
2966f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
2976f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                sp<AMessage> notify = mNotify->dup();
2986f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                notify->setInt32("sessionID", mSessionID);
2996f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                notify->setInt32("reason", kWhatDatagram);
3006f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3016f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                uint32_t ip = ntohl(remoteAddr.sin_addr.s_addr);
3026f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                notify->setString(
3036f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                        "fromAddr",
3046f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                        StringPrintf(
3056f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            "%u.%u.%u.%u",
3066f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            ip >> 24,
3076f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            (ip >> 16) & 0xff,
3086f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            (ip >> 8) & 0xff,
3096f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            ip & 0xff).c_str());
3106f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3116f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                notify->setInt32("fromPort", ntohs(remoteAddr.sin_port));
3126f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3136f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                notify->setBuffer("data", buf);
3146f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                notify->post();
3156f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            }
3166f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        } while (err == OK);
3176f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3186f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (err == -EAGAIN) {
3196f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            err = OK;
3206f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
3216f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3226f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (err != OK) {
32399f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang            if (!mUDPRetries) {
32499f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                notifyError(false /* send */, err, "Recvfrom failed.");
32599f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                mSawReceiveFailure = true;
32699f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang            } else {
32799f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                mUDPRetries--;
32899f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                ALOGE("Recvfrom failed, %d/%d retries left",
32999f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                        mUDPRetries, kMaxUDPRetries);
33099f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                err = OK;
33199f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang            }
33299f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang        } else {
33399f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang            mUDPRetries = kMaxUDPRetries;
3346f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
3356f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3366f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return err;
3376f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
3386f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3396f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    char tmp[512];
3406f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    ssize_t n;
3416f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    do {
3426f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        n = recv(mSocket, tmp, sizeof(tmp), 0);
3436f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    } while (n < 0 && errno == EINTR);
3446f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3456f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    status_t err = OK;
3466f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3476f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (n > 0) {
3486f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        mInBuffer.append(tmp, n);
3496f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3506f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#if 0
3516f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        ALOGI("in:");
3526f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        hexdump(tmp, n);
3536f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#endif
3546f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    } else if (n < 0) {
3556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        err = -errno;
3566f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    } else {
3576f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        err = -ECONNRESET;
3586f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
3596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3608060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    if (mMode == MODE_DATAGRAM) {
3617d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        // TCP stream carrying 16-bit length-prefixed datagrams.
3626f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3637d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        while (mInBuffer.size() >= 2) {
3647d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            size_t packetSize = U16_AT((const uint8_t *)mInBuffer.c_str());
3656f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3667d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            if (mInBuffer.size() < packetSize + 2) {
3676f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                break;
3686f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            }
3696f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3707d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            sp<ABuffer> packet = new ABuffer(packetSize);
3717d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            memcpy(packet->data(), mInBuffer.c_str() + 2, packetSize);
3727d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
37343433111d4adff6a138447dfadf531046497a008Andreas Huber            int64_t nowUs = ALooper::GetNowUs();
37443433111d4adff6a138447dfadf531046497a008Andreas Huber            packet->meta()->setInt64("arrivalTimeUs", nowUs);
37543433111d4adff6a138447dfadf531046497a008Andreas Huber
3766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            sp<AMessage> notify = mNotify->dup();
3776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            notify->setInt32("sessionID", mSessionID);
3787d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            notify->setInt32("reason", kWhatDatagram);
3797d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            notify->setBuffer("data", packet);
3807d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            notify->post();
3816f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3827d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            mInBuffer.erase(0, packetSize + 2);
3837d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        }
3848060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    } else if (mMode == MODE_RTSP) {
3857d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        for (;;) {
3867d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            size_t length;
3876f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3887d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            if (mInBuffer.size() > 0 && mInBuffer.c_str()[0] == '$') {
3897d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                if (mInBuffer.size() < 4) {
3907d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                    break;
3917d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                }
3926f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3937d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                length = U16_AT((const uint8_t *)mInBuffer.c_str() + 2);
3946f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3957d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                if (mInBuffer.size() < 4 + length) {
3967d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                    break;
3977d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                }
3986f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
3997d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                sp<AMessage> notify = mNotify->dup();
4007d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                notify->setInt32("sessionID", mSessionID);
4017d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                notify->setInt32("reason", kWhatBinaryData);
4027d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                notify->setInt32("channel", mInBuffer.c_str()[1]);
4036f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
4047d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                sp<ABuffer> data = new ABuffer(length);
4057d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                memcpy(data->data(), mInBuffer.c_str() + 4, length);
4066f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
4077d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                int64_t nowUs = ALooper::GetNowUs();
4087d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                data->meta()->setInt64("arrivalTimeUs", nowUs);
4097d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
4107d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                notify->setBuffer("data", data);
4117d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                notify->post();
4127d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
4137d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                mInBuffer.erase(0, 4 + length);
4147d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                continue;
4157d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            }
4167d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
4177d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            sp<ParsedMessage> msg =
4187d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                ParsedMessage::Parse(
4197d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                        mInBuffer.c_str(), mInBuffer.size(), err != OK, &length);
4207d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
4217d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            if (msg == NULL) {
4227d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                break;
4237d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            }
4247d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
4257d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            sp<AMessage> notify = mNotify->dup();
4267d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            notify->setInt32("sessionID", mSessionID);
4277d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            notify->setInt32("reason", kWhatData);
4287d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            notify->setObject("data", msg);
4297d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            notify->post();
4306f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
4316f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#if 1
4327d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            // XXX The (old) dongle sends the wrong content length header on a
4337d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            // SET_PARAMETER request that signals a "wfd_idr_request".
4347d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            // (17 instead of 19).
4357d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            const char *content = msg->getContent();
4367d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            if (content
4377d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                    && !memcmp(content, "wfd_idr_request\r\n", 17)
4387d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                    && length >= 19
4397d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                    && mInBuffer.c_str()[length] == '\r'
4407d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                    && mInBuffer.c_str()[length + 1] == '\n') {
4417d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                length += 2;
4427d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            }
4436f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber#endif
4446f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
4457d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            mInBuffer.erase(0, length);
4466f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
4477d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            if (err != OK) {
4487d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                break;
4497d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            }
4506f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
4518060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    } else {
4528060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        CHECK_EQ(mMode, MODE_WEBSOCKET);
4538060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
4548060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        const uint8_t *data = (const uint8_t *)mInBuffer.c_str();
4558060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        // hexdump(data, mInBuffer.size());
4568060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
4578060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        while (mInBuffer.size() >= 2) {
4588060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            size_t offset = 2;
4598060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
4608060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            unsigned payloadLen = data[1] & 0x7f;
4618060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            if (payloadLen == 126) {
4628060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                if (offset + 2 > mInBuffer.size()) {
4638060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                    break;
4648060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                }
4658060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
4668060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                payloadLen = U16_AT(&data[offset]);
4678060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                offset += 2;
4688060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            } else if (payloadLen == 127) {
4698060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                if (offset + 8 > mInBuffer.size()) {
4708060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                    break;
4718060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                }
4728060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
4738060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                payloadLen = U64_AT(&data[offset]);
4748060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                offset += 8;
4758060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            }
4768060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
4778060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            uint32_t mask = 0;
4788060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            if (data[1] & 0x80) {
4798060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                // MASK==1
4808060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                if (offset + 4 > mInBuffer.size()) {
4818060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                    break;
4828060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                }
4838060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
4848060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                mask = U32_AT(&data[offset]);
4858060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                offset += 4;
4868060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            }
4878060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
4888060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            if (offset + payloadLen > mInBuffer.size()) {
4898060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                break;
4908060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            }
4918060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
4928060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            // We have the full message.
4938060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
4948060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            sp<ABuffer> packet = new ABuffer(payloadLen);
4958060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            memcpy(packet->data(), &data[offset], payloadLen);
4968060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
4978060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            if (mask != 0) {
4988060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                for (size_t i = 0; i < payloadLen; ++i) {
4998060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                    packet->data()[i] =
5008060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                        data[offset + i]
5018060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                            ^ ((mask >> (8 * (3 - (i % 4)))) & 0xff);
5028060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                }
5038060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            }
5048060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
5058060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            sp<AMessage> notify = mNotify->dup();
5068060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            notify->setInt32("sessionID", mSessionID);
5078060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            notify->setInt32("reason", kWhatWebSocketMessage);
5088060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            notify->setBuffer("data", packet);
5098060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            notify->setInt32("headerByte", data[0]);
5108060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            notify->post();
5118060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
5128060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            mInBuffer.erase(0, offset + payloadLen);
5138060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        }
5146f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
5156f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
5166f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (err != OK) {
5176f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        notifyError(false /* send */, err, "Recv failed.");
5186f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        mSawReceiveFailure = true;
5196f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
5206f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
5216f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return err;
5226f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
5236f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
524d411b4ca2945cd8974a3a78199fce94646950128Andreas Hubervoid ANetworkSession::Session::dumpFragmentStats(const Fragment & /* frag */) {
525632177b7446185a0407b7df96f684a9b8b980765Andreas Huber#if 0
526632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    int64_t nowUs = ALooper::GetNowUs();
527632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    int64_t delayMs = (nowUs - frag.mTimeUs) / 1000ll;
528632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
529632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    static const int64_t kMinDelayMs = 0;
530632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    static const int64_t kMaxDelayMs = 300;
531632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
532632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    const char *kPattern = "########################################";
533632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    size_t kPatternSize = strlen(kPattern);
534632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
535632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    int n = (kPatternSize * (delayMs - kMinDelayMs))
536632177b7446185a0407b7df96f684a9b8b980765Andreas Huber                / (kMaxDelayMs - kMinDelayMs);
537632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
538632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    if (n < 0) {
539632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        n = 0;
540632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    } else if ((size_t)n > kPatternSize) {
541632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        n = kPatternSize;
542632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    }
543632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
544632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    ALOGI("[%lld]: (%4lld ms) %s\n",
545632177b7446185a0407b7df96f684a9b8b980765Andreas Huber          frag.mTimeUs / 1000,
546632177b7446185a0407b7df96f684a9b8b980765Andreas Huber          delayMs,
547632177b7446185a0407b7df96f684a9b8b980765Andreas Huber          kPattern + kPatternSize - n);
548632177b7446185a0407b7df96f684a9b8b980765Andreas Huber#endif
549632177b7446185a0407b7df96f684a9b8b980765Andreas Huber}
550632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
5516f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::Session::writeMore() {
5526f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (mState == DATAGRAM) {
553632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        CHECK(!mOutFragments.empty());
5546f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
5556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        status_t err;
5566f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        do {
557632177b7446185a0407b7df96f684a9b8b980765Andreas Huber            const Fragment &frag = *mOutFragments.begin();
558632177b7446185a0407b7df96f684a9b8b980765Andreas Huber            const sp<ABuffer> &datagram = frag.mBuffer;
5596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
5606f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            int n;
5616f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            do {
562bd4e99c1636c75f6db0be70434b9f276bfecd96dAndreas Huber                n = send(mSocket, datagram->data(), datagram->size(), 0);
5636f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            } while (n < 0 && errno == EINTR);
5646f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
5656f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            err = OK;
5666f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
5676f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            if (n > 0) {
568632177b7446185a0407b7df96f684a9b8b980765Andreas Huber                if (frag.mFlags & FRAGMENT_FLAG_TIME_VALID) {
569632177b7446185a0407b7df96f684a9b8b980765Andreas Huber                    dumpFragmentStats(frag);
570632177b7446185a0407b7df96f684a9b8b980765Andreas Huber                }
571632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
572632177b7446185a0407b7df96f684a9b8b980765Andreas Huber                mOutFragments.erase(mOutFragments.begin());
5736f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            } else if (n < 0) {
5746f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                err = -errno;
5756f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            } else if (n == 0) {
5766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                err = -ECONNRESET;
5776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            }
578632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        } while (err == OK && !mOutFragments.empty());
5796f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
5806f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (err == -EAGAIN) {
581632177b7446185a0407b7df96f684a9b8b980765Andreas Huber            if (!mOutFragments.empty()) {
58267c036a3faada8b77d73cf81bd1b0be4cb60c562Colin Cross                ALOGI("%zu datagrams remain queued.", mOutFragments.size());
58383c9bd167600b3ff77008a6c06c05bb1f189d4caAndreas Huber            }
5846f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            err = OK;
5856f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
5866f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
5876f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (err != OK) {
58899f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang            if (!mUDPRetries) {
58999f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                notifyError(true /* send */, err, "Send datagram failed.");
59099f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                mSawSendFailure = true;
59199f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang            } else {
59299f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                mUDPRetries--;
59399f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                ALOGE("Send datagram failed, %d/%d retries left",
59499f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                        mUDPRetries, kMaxUDPRetries);
59599f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang                err = OK;
59699f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang            }
59799f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang        } else {
59899f27cdf2c2711aa0c8b4d9ae4d12cae37ff94f6Chong Zhang            mUDPRetries = kMaxUDPRetries;
5996f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
6006f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
6016f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return err;
6026f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
6036f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
6046f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (mState == CONNECTING) {
6056f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        int err;
6066f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        socklen_t optionLen = sizeof(err);
6076f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        CHECK_EQ(getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &err, &optionLen), 0);
6086f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        CHECK_EQ(optionLen, (socklen_t)sizeof(err));
6096f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
6106f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (err != 0) {
6116f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            notifyError(kWhatError, -err, "Connection failed");
6126f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            mSawSendFailure = true;
6136f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
6147d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            return -err;
6156f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
6166f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
6176f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        mState = CONNECTED;
6186f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        notify(kWhatConnected);
6196f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
6206f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return OK;
6216f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
6226f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
6236f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    CHECK_EQ(mState, CONNECTED);
624632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    CHECK(!mOutFragments.empty());
6256f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
6265d5f8a5d3cf24b5dcf1267ef512b24caa695787aAmit Pundir    ssize_t n = -1;
627632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    while (!mOutFragments.empty()) {
628632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        const Fragment &frag = *mOutFragments.begin();
6296f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
630632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        do {
631632177b7446185a0407b7df96f684a9b8b980765Andreas Huber            n = send(mSocket, frag.mBuffer->data(), frag.mBuffer->size(), 0);
632632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        } while (n < 0 && errno == EINTR);
6336f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
634632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        if (n <= 0) {
635632177b7446185a0407b7df96f684a9b8b980765Andreas Huber            break;
636632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        }
6376f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
638632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        frag.mBuffer->setRange(
639632177b7446185a0407b7df96f684a9b8b980765Andreas Huber                frag.mBuffer->offset() + n, frag.mBuffer->size() - n);
640632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
641632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        if (frag.mBuffer->size() > 0) {
642632177b7446185a0407b7df96f684a9b8b980765Andreas Huber            break;
643632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        }
644632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
645632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        if (frag.mFlags & FRAGMENT_FLAG_TIME_VALID) {
646632177b7446185a0407b7df96f684a9b8b980765Andreas Huber            dumpFragmentStats(frag);
647632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        }
648632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
649632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        mOutFragments.erase(mOutFragments.begin());
650632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    }
651632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
652632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    status_t err = OK;
653632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
654632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    if (n < 0) {
6556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        err = -errno;
6566f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    } else if (n == 0) {
6576f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        err = -ECONNRESET;
6586f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
6596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
6606f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (err != OK) {
6616f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        notifyError(true /* send */, err, "Send failed.");
6626f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        mSawSendFailure = true;
6636f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
6646f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
665dca73b8fe8fa4d991e1a78c02f1939aaeb673cc1Andreas Huber#if 0
6669dffd24e00a1b2abd5e2dcc2366c0327ec3701b8Andreas Huber    int numBytesQueued;
6679dffd24e00a1b2abd5e2dcc2366c0327ec3701b8Andreas Huber    int res = ioctl(mSocket, SIOCOUTQ, &numBytesQueued);
668e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber    if (res == 0 && numBytesQueued > 50 * 1024) {
669e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber        if (numBytesQueued > 409600) {
670e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber            ALOGW("!!! numBytesQueued = %d", numBytesQueued);
671e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber        }
672e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber
673e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber        int64_t nowUs = ALooper::GetNowUs();
674e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber
675e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber        if (mLastStallReportUs < 0ll
676dca73b8fe8fa4d991e1a78c02f1939aaeb673cc1Andreas Huber                || nowUs > mLastStallReportUs + 100000ll) {
677e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber            sp<AMessage> msg = mNotify->dup();
678e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber            msg->setInt32("sessionID", mSessionID);
679e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber            msg->setInt32("reason", kWhatNetworkStall);
680e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber            msg->setSize("numBytesQueued", numBytesQueued);
681e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber            msg->post();
682e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber
683e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber            mLastStallReportUs = nowUs;
684e2aef54fee88fdeb585a41e1e9834e3d975b263cAndreas Huber        }
6859dffd24e00a1b2abd5e2dcc2366c0327ec3701b8Andreas Huber    }
6869dffd24e00a1b2abd5e2dcc2366c0327ec3701b8Andreas Huber#endif
6879dffd24e00a1b2abd5e2dcc2366c0327ec3701b8Andreas Huber
6886f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return err;
6896f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
6906f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
691632177b7446185a0407b7df96f684a9b8b980765Andreas Huberstatus_t ANetworkSession::Session::sendRequest(
692632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        const void *data, ssize_t size, bool timeValid, int64_t timeUs) {
6936f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    CHECK(mState == CONNECTED || mState == DATAGRAM);
6946f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
695632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    if (size < 0) {
696632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        size = strlen((const char *)data);
697632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    }
698bd4e99c1636c75f6db0be70434b9f276bfecd96dAndreas Huber
699632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    if (size == 0) {
700bd4e99c1636c75f6db0be70434b9f276bfecd96dAndreas Huber        return OK;
701bd4e99c1636c75f6db0be70434b9f276bfecd96dAndreas Huber    }
702bd4e99c1636c75f6db0be70434b9f276bfecd96dAndreas Huber
703632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    sp<ABuffer> buffer;
704632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
7058060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    if (mState == CONNECTED && mMode == MODE_DATAGRAM) {
7067d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        CHECK_LE(size, 65535);
7077d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
708632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        buffer = new ABuffer(size + 2);
709632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        buffer->data()[0] = size >> 8;
710632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        buffer->data()[1] = size & 0xff;
711632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        memcpy(buffer->data() + 2, data, size);
7128060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    } else if (mState == CONNECTED && mMode == MODE_WEBSOCKET) {
7138060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        static const bool kUseMask = false;  // Chromium doesn't like it.
7148060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
7158060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        size_t numHeaderBytes = 2 + (kUseMask ? 4 : 0);
7168060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        if (size > 65535) {
7178060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            numHeaderBytes += 8;
7188060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        } else if (size > 125) {
7198060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            numHeaderBytes += 2;
7208060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        }
7218060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
7228060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        buffer = new ABuffer(numHeaderBytes + size);
7238060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        buffer->data()[0] = 0x81;  // FIN==1 | opcode=1 (text)
7248060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        buffer->data()[1] = kUseMask ? 0x80 : 0x00;
7258060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
7268060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        if (size > 65535) {
7278060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[1] |= 127;
7288060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[2] = 0x00;
7298060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[3] = 0x00;
7308060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[4] = 0x00;
7318060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[5] = 0x00;
7328060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[6] = (size >> 24) & 0xff;
7338060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[7] = (size >> 16) & 0xff;
7348060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[8] = (size >> 8) & 0xff;
7358060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[9] = size & 0xff;
7368060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        } else if (size > 125) {
7378060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[1] |= 126;
7388060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[2] = (size >> 8) & 0xff;
7398060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[3] = size & 0xff;
7408060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        } else {
7418060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[1] |= size;
7428060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        }
7438060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
7448060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        if (kUseMask) {
7458060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            uint32_t mask = rand();
7468060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
7478060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[numHeaderBytes - 4] = (mask >> 24) & 0xff;
7488060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[numHeaderBytes - 3] = (mask >> 16) & 0xff;
7498060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[numHeaderBytes - 2] = (mask >> 8) & 0xff;
7508060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            buffer->data()[numHeaderBytes - 1] = mask & 0xff;
7518060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
7528060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            for (size_t i = 0; i < (size_t)size; ++i) {
7538060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                buffer->data()[numHeaderBytes + i] =
7548060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                    ((const uint8_t *)data)[i]
7558060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                        ^ ((mask >> (8 * (3 - (i % 4)))) & 0xff);
7568060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            }
7578060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        } else {
7588060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber            memcpy(buffer->data() + numHeaderBytes, data, size);
7598060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        }
760632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    } else {
761632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        buffer = new ABuffer(size);
762632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        memcpy(buffer->data(), data, size);
763632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    }
7647d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
765632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    Fragment frag;
766632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
767632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    frag.mFlags = 0;
768632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    if (timeValid) {
769632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        frag.mFlags = FRAGMENT_FLAG_TIME_VALID;
770632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        frag.mTimeUs = timeUs;
7717d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    }
7727d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
773632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    frag.mBuffer = buffer;
774632177b7446185a0407b7df96f684a9b8b980765Andreas Huber
775632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    mOutFragments.push_back(frag);
7766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
7776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return OK;
7786f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
7796f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
7806f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Hubervoid ANetworkSession::Session::notifyError(
7816f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        bool send, status_t err, const char *detail) {
7826f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    sp<AMessage> msg = mNotify->dup();
7836f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    msg->setInt32("sessionID", mSessionID);
7846f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    msg->setInt32("reason", kWhatError);
7856f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    msg->setInt32("send", send);
7866f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    msg->setInt32("err", err);
7876f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    msg->setString("detail", detail);
7886f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    msg->post();
7896f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
7906f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
7916f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Hubervoid ANetworkSession::Session::notify(NotificationReason reason) {
7926f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    sp<AMessage> msg = mNotify->dup();
7936f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    msg->setInt32("sessionID", mSessionID);
7946f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    msg->setInt32("reason", reason);
7956f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    msg->post();
7966f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
7976f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
7986f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber////////////////////////////////////////////////////////////////////////////////
7996f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8006f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas HuberANetworkSession::ANetworkSession()
8016f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    : mNextSessionID(1) {
8026f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    mPipeFd[0] = mPipeFd[1] = -1;
8036f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
8046f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8056f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas HuberANetworkSession::~ANetworkSession() {
8066f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    stop();
8076f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
8086f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8096f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::start() {
8106f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (mThread != NULL) {
8116f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return INVALID_OPERATION;
8126f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
8136f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8146f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    int res = pipe(mPipeFd);
8156f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (res != 0) {
8166f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        mPipeFd[0] = mPipeFd[1] = -1;
8176f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return -errno;
8186f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
8196f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8206f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    mThread = new NetworkThread(this);
8216f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8226f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    status_t err = mThread->run("ANetworkSession", ANDROID_PRIORITY_AUDIO);
8236f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8246f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (err != OK) {
8256f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        mThread.clear();
8266f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8276f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        close(mPipeFd[0]);
8286f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        close(mPipeFd[1]);
8296f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        mPipeFd[0] = mPipeFd[1] = -1;
8306f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8316f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return err;
8326f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
8336f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8346f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return OK;
8356f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
8366f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8376f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::stop() {
8386f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (mThread == NULL) {
8396f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return INVALID_OPERATION;
8406f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
8416f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8426f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    mThread->requestExit();
8436f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    interrupt();
8446f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    mThread->requestExitAndWait();
8456f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8466f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    mThread.clear();
8476f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8486f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    close(mPipeFd[0]);
8496f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    close(mPipeFd[1]);
8506f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    mPipeFd[0] = mPipeFd[1] = -1;
8516f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8526f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return OK;
8536f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
8546f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::createRTSPClient(
8566f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        const char *host, unsigned port, const sp<AMessage> &notify,
8576f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        int32_t *sessionID) {
8586f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return createClientOrServer(
8596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            kModeCreateRTSPClient,
860ab1bd84889273bc21efdabe5ff6f4633eb918a85Andreas Huber            NULL /* addr */,
8616f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            0 /* port */,
8626f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            host,
8636f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            port,
8646f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            notify,
8656f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            sessionID);
8666f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
8676f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8686f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::createRTSPServer(
869ab1bd84889273bc21efdabe5ff6f4633eb918a85Andreas Huber        const struct in_addr &addr, unsigned port,
870ab1bd84889273bc21efdabe5ff6f4633eb918a85Andreas Huber        const sp<AMessage> &notify, int32_t *sessionID) {
8716f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return createClientOrServer(
8726f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            kModeCreateRTSPServer,
873ab1bd84889273bc21efdabe5ff6f4633eb918a85Andreas Huber            &addr,
8746f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            port,
8756f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            NULL /* remoteHost */,
8766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            0 /* remotePort */,
8776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            notify,
8786f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            sessionID);
8796f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
8806f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8816f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::createUDPSession(
8826f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        unsigned localPort, const sp<AMessage> &notify, int32_t *sessionID) {
8836f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return createUDPSession(localPort, NULL, 0, notify, sessionID);
8846f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
8856f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
8866f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::createUDPSession(
8876f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        unsigned localPort,
8886f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        const char *remoteHost,
8896f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        unsigned remotePort,
8906f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        const sp<AMessage> &notify,
8916f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        int32_t *sessionID) {
8926f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return createClientOrServer(
8936f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            kModeCreateUDPSession,
894ab1bd84889273bc21efdabe5ff6f4633eb918a85Andreas Huber            NULL /* addr */,
8956f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            localPort,
8966f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            remoteHost,
8976f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            remotePort,
8986f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            notify,
8996f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            sessionID);
9006f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
9016f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9027d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huberstatus_t ANetworkSession::createTCPDatagramSession(
9037d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        const struct in_addr &addr, unsigned port,
9047d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        const sp<AMessage> &notify, int32_t *sessionID) {
9057d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    return createClientOrServer(
9067d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            kModeCreateTCPDatagramSessionPassive,
9077d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            &addr,
9087d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            port,
9097d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            NULL /* remoteHost */,
9107d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            0 /* remotePort */,
9117d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            notify,
9127d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            sessionID);
9137d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber}
9147d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
9157d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huberstatus_t ANetworkSession::createTCPDatagramSession(
9167d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        unsigned localPort,
9177d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        const char *remoteHost,
9187d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        unsigned remotePort,
9197d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        const sp<AMessage> &notify,
9207d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        int32_t *sessionID) {
9217d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    return createClientOrServer(
9227d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            kModeCreateTCPDatagramSessionActive,
9237d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            NULL /* addr */,
9247d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            localPort,
9257d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            remoteHost,
9267d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            remotePort,
9277d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            notify,
9287d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            sessionID);
9297d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber}
9307d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
9316f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::destroySession(int32_t sessionID) {
9326f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    Mutex::Autolock autoLock(mLock);
9336f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9346f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    ssize_t index = mSessions.indexOfKey(sessionID);
9356f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9366f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (index < 0) {
9376f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return -ENOENT;
9386f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
9396f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9406f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    mSessions.removeItemsAt(index);
9416f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9426f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    interrupt();
9436f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9446f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return OK;
9456f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
9466f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9476f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber// static
9486f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::MakeSocketNonBlocking(int s) {
9496f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    int flags = fcntl(s, F_GETFL, 0);
9506f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (flags < 0) {
9516f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        flags = 0;
9526f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
9536f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9546f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    int res = fcntl(s, F_SETFL, flags | O_NONBLOCK);
9556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (res < 0) {
9566f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return -errno;
9576f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
9586f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return OK;
9606f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
9616f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9626f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::createClientOrServer(
9636f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        Mode mode,
964ab1bd84889273bc21efdabe5ff6f4633eb918a85Andreas Huber        const struct in_addr *localAddr,
9656f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        unsigned port,
9666f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        const char *remoteHost,
9676f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        unsigned remotePort,
9686f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        const sp<AMessage> &notify,
9696f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        int32_t *sessionID) {
9706f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    Mutex::Autolock autoLock(mLock);
9716f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9726f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    *sessionID = 0;
9736f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    status_t err = OK;
9746f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    int s, res;
9756f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    sp<Session> session;
9766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    s = socket(
9786f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            AF_INET,
9796f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            (mode == kModeCreateUDPSession) ? SOCK_DGRAM : SOCK_STREAM,
9806f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            0);
9816f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9826f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (s < 0) {
9836f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        err = -errno;
9846f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        goto bail;
9856f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
9866f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9877d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    if (mode == kModeCreateRTSPServer
9887d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            || mode == kModeCreateTCPDatagramSessionPassive) {
9896f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        const int yes = 1;
9906f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        res = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
9916f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9926f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (res < 0) {
9936f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            err = -errno;
9946f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            goto bail2;
9956f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
9966f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
9976f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
9986f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (mode == kModeCreateUDPSession) {
9996f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        int size = 256 * 1024;
10006f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10016f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        res = setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
10026f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10036f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (res < 0) {
10046f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            err = -errno;
10056f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            goto bail2;
10066f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
10076f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10086f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        res = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
10096f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10106f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (res < 0) {
10116f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            err = -errno;
10126f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            goto bail2;
10136f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
101443433111d4adff6a138447dfadf531046497a008Andreas Huber    } else if (mode == kModeCreateTCPDatagramSessionActive) {
101543433111d4adff6a138447dfadf531046497a008Andreas Huber        int flag = 1;
101643433111d4adff6a138447dfadf531046497a008Andreas Huber        res = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
101743433111d4adff6a138447dfadf531046497a008Andreas Huber
101843433111d4adff6a138447dfadf531046497a008Andreas Huber        if (res < 0) {
101943433111d4adff6a138447dfadf531046497a008Andreas Huber            err = -errno;
102043433111d4adff6a138447dfadf531046497a008Andreas Huber            goto bail2;
102143433111d4adff6a138447dfadf531046497a008Andreas Huber        }
10226e8aec8d185444e52ff0247b266f614c690ded13Andreas Huber
10236e8aec8d185444e52ff0247b266f614c690ded13Andreas Huber        int tos = 224;  // VOICE
10246e8aec8d185444e52ff0247b266f614c690ded13Andreas Huber        res = setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
10256e8aec8d185444e52ff0247b266f614c690ded13Andreas Huber
10266e8aec8d185444e52ff0247b266f614c690ded13Andreas Huber        if (res < 0) {
10276e8aec8d185444e52ff0247b266f614c690ded13Andreas Huber            err = -errno;
10286e8aec8d185444e52ff0247b266f614c690ded13Andreas Huber            goto bail2;
10296e8aec8d185444e52ff0247b266f614c690ded13Andreas Huber        }
10306f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
10316f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10326f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    err = MakeSocketNonBlocking(s);
10336f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10346f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (err != OK) {
10356f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        goto bail2;
10366f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
10376f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10386f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    struct sockaddr_in addr;
10396f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
10406f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    addr.sin_family = AF_INET;
10416f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10427d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    if (mode == kModeCreateRTSPClient
10437d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            || mode == kModeCreateTCPDatagramSessionActive) {
10446f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        struct hostent *ent= gethostbyname(remoteHost);
10456f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (ent == NULL) {
10466f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            err = -h_errno;
10476f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            goto bail2;
10486f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
10496f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10506f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
10516f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        addr.sin_port = htons(remotePort);
1052ab1bd84889273bc21efdabe5ff6f4633eb918a85Andreas Huber    } else if (localAddr != NULL) {
1053ab1bd84889273bc21efdabe5ff6f4633eb918a85Andreas Huber        addr.sin_addr = *localAddr;
1054ab1bd84889273bc21efdabe5ff6f4633eb918a85Andreas Huber        addr.sin_port = htons(port);
10556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    } else {
1056ab1bd84889273bc21efdabe5ff6f4633eb918a85Andreas Huber        addr.sin_addr.s_addr = htonl(INADDR_ANY);
10576f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        addr.sin_port = htons(port);
10586f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
10596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10607d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    if (mode == kModeCreateRTSPClient
10617d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            || mode == kModeCreateTCPDatagramSessionActive) {
10627d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        in_addr_t x = ntohl(addr.sin_addr.s_addr);
10637d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        ALOGI("connecting socket %d to %d.%d.%d.%d:%d",
10647d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber              s,
10657d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber              (x >> 24),
10667d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber              (x >> 16) & 0xff,
10677d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber              (x >> 8) & 0xff,
10687d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber              x & 0xff,
10697d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber              ntohs(addr.sin_port));
10707d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
10716f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        res = connect(s, (const struct sockaddr *)&addr, sizeof(addr));
10726f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10736f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        CHECK_LT(res, 0);
10746f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (errno == EINPROGRESS) {
10756f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            res = 0;
10766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
10776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    } else {
10786f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        res = bind(s, (const struct sockaddr *)&addr, sizeof(addr));
10796f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10806f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (res == 0) {
10817d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            if (mode == kModeCreateRTSPServer
10827d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                    || mode == kModeCreateTCPDatagramSessionPassive) {
10836f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                res = listen(s, 4);
10846f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            } else {
10856f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                CHECK_EQ(mode, kModeCreateUDPSession);
10866f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10876f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                if (remoteHost != NULL) {
10886f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    struct sockaddr_in remoteAddr;
10896f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    memset(remoteAddr.sin_zero, 0, sizeof(remoteAddr.sin_zero));
10906f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    remoteAddr.sin_family = AF_INET;
10916f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    remoteAddr.sin_port = htons(remotePort);
10926f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10936f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    struct hostent *ent= gethostbyname(remoteHost);
10946f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    if (ent == NULL) {
10956f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                        err = -h_errno;
10966f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                        goto bail2;
10976f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    }
10986f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
10996f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    remoteAddr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
11006f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11016f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    res = connect(
11026f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            s,
11036f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            (const struct sockaddr *)&remoteAddr,
11046f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            sizeof(remoteAddr));
11056f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                }
11066f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            }
11076f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
11086f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
11096f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11106f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (res < 0) {
11116f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        err = -errno;
11126f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        goto bail2;
11136f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
11146f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11156f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    Session::State state;
11166f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    switch (mode) {
11176f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        case kModeCreateRTSPClient:
11186f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            state = Session::CONNECTING;
11196f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            break;
11206f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11217d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        case kModeCreateTCPDatagramSessionActive:
11227d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            state = Session::CONNECTING;
11237d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            break;
11247d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
11257d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber        case kModeCreateTCPDatagramSessionPassive:
11267d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            state = Session::LISTENING_TCP_DGRAMS;
11277d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            break;
11287d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
11296f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        case kModeCreateRTSPServer:
11307d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber            state = Session::LISTENING_RTSP;
11316f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            break;
11326f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11336f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        default:
11346f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            CHECK_EQ(mode, kModeCreateUDPSession);
11356f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            state = Session::DATAGRAM;
11366f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            break;
11376f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
11386f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11396f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    session = new Session(
11406f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            mNextSessionID++,
11416f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            state,
11426f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            s,
11436f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            notify);
11446f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11457d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    if (mode == kModeCreateTCPDatagramSessionActive) {
11468060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        session->setMode(Session::MODE_DATAGRAM);
11477d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    } else if (mode == kModeCreateRTSPClient) {
11488060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        session->setMode(Session::MODE_RTSP);
11497d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    }
11507d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
11516f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    mSessions.add(session->sessionID(), session);
11526f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11536f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    interrupt();
11546f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    *sessionID = session->sessionID();
11566f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11576f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    goto bail;
11586f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberbail2:
11606f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    close(s);
11616f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    s = -1;
11626f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11636f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberbail:
11646f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return err;
11656f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
11666f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11676f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::connectUDPSession(
11686f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        int32_t sessionID, const char *remoteHost, unsigned remotePort) {
11696f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    Mutex::Autolock autoLock(mLock);
11706f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11716f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    ssize_t index = mSessions.indexOfKey(sessionID);
11726f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11736f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (index < 0) {
11746f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return -ENOENT;
11756f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
11766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    const sp<Session> session = mSessions.valueAt(index);
11786f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    int s = session->socket();
11796f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11806f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    struct sockaddr_in remoteAddr;
11816f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    memset(remoteAddr.sin_zero, 0, sizeof(remoteAddr.sin_zero));
11826f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    remoteAddr.sin_family = AF_INET;
11836f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    remoteAddr.sin_port = htons(remotePort);
11846f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11856f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    status_t err = OK;
11867d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber    struct hostent *ent = gethostbyname(remoteHost);
11876f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (ent == NULL) {
11886f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        err = -h_errno;
11896f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    } else {
11906f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        remoteAddr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
11916f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11926f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        int res = connect(
11936f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                s,
11946f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                (const struct sockaddr *)&remoteAddr,
11956f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                sizeof(remoteAddr));
11966f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
11976f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (res < 0) {
11986f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            err = -errno;
11996f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
12006f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
12016f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12026f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return err;
12036f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
12046f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12056f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huberstatus_t ANetworkSession::sendRequest(
1206632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        int32_t sessionID, const void *data, ssize_t size,
1207632177b7446185a0407b7df96f684a9b8b980765Andreas Huber        bool timeValid, int64_t timeUs) {
12086f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    Mutex::Autolock autoLock(mLock);
12096f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12106f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    ssize_t index = mSessions.indexOfKey(sessionID);
12116f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12126f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (index < 0) {
12136f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return -ENOENT;
12146f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
12156f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12166f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    const sp<Session> session = mSessions.valueAt(index);
12176f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1218632177b7446185a0407b7df96f684a9b8b980765Andreas Huber    status_t err = session->sendRequest(data, size, timeValid, timeUs);
12196f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12206f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    interrupt();
12216f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12226f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    return err;
12236f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
12246f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12258060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huberstatus_t ANetworkSession::switchToWebSocketMode(int32_t sessionID) {
12268060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    Mutex::Autolock autoLock(mLock);
12278060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
12288060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    ssize_t index = mSessions.indexOfKey(sessionID);
12298060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
12308060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    if (index < 0) {
12318060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber        return -ENOENT;
12328060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    }
12338060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
12348060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    const sp<Session> session = mSessions.valueAt(index);
12358060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber    return session->switchToWebSocketMode();
12368060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber}
12378060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber
12386f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Hubervoid ANetworkSession::interrupt() {
12396f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    static const char dummy = 0;
12406f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12416f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    ssize_t n;
12426f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    do {
12436f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        n = write(mPipeFd[1], &dummy, 1);
12446f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    } while (n < 0 && errno == EINTR);
12456f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12466f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (n < 0) {
12476f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        ALOGW("Error writing to pipe (%s)", strerror(errno));
12486f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
12496f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
12506f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12516f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Hubervoid ANetworkSession::threadLoop() {
12526f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    fd_set rs, ws;
12536f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    FD_ZERO(&rs);
12546f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    FD_ZERO(&ws);
12556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12566f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    FD_SET(mPipeFd[0], &rs);
12576f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    int maxFd = mPipeFd[0];
12586f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    {
12606f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        Mutex::Autolock autoLock(mLock);
12616f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12626f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        for (size_t i = 0; i < mSessions.size(); ++i) {
12636f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            const sp<Session> &session = mSessions.valueAt(i);
12646f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12656f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            int s = session->socket();
12666f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12676f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            if (s < 0) {
12686f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                continue;
12696f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            }
12706f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12716f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            if (session->wantsToRead()) {
12726f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                FD_SET(s, &rs);
12736f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                if (s > maxFd) {
12746f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    maxFd = s;
12756f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                }
12766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            }
12776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12786f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            if (session->wantsToWrite()) {
12796f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                FD_SET(s, &ws);
12806f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                if (s > maxFd) {
12816f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    maxFd = s;
12826f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                }
12836f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            }
12846f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
12856f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
12866f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12876f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    int res = select(maxFd + 1, &rs, &ws, NULL, NULL /* tv */);
12886f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12896f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (res == 0) {
12906f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return;
12916f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
12926f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12936f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (res < 0) {
12946f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (errno == EINTR) {
12956f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            return;
12966f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
12976f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
12986f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        ALOGE("select failed w/ error %d (%s)", errno, strerror(errno));
12996f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        return;
13006f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
13016f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13026f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    if (FD_ISSET(mPipeFd[0], &rs)) {
13036f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        char c;
13046f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        ssize_t n;
13056f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        do {
13066f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            n = read(mPipeFd[0], &c, 1);
13076f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        } while (n < 0 && errno == EINTR);
13086f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13096f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        if (n < 0) {
13106f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            ALOGW("Error reading from pipe (%s)", strerror(errno));
13116f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
13126f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13136f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        --res;
13146f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
13156f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13166f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    {
13176f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        Mutex::Autolock autoLock(mLock);
13186f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13196f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        List<sp<Session> > sessionsToAdd;
13206f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13216f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        for (size_t i = mSessions.size(); res > 0 && i-- > 0;) {
13226f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            const sp<Session> &session = mSessions.valueAt(i);
13236f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13246f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            int s = session->socket();
13256f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13266f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            if (s < 0) {
13276f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                continue;
13286f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            }
13296f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13306f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            if (FD_ISSET(s, &rs) || FD_ISSET(s, &ws)) {
13316f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                --res;
13326f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            }
13336f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13346f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            if (FD_ISSET(s, &rs)) {
13357d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber                if (session->isRTSPServer() || session->isTCPDatagramServer()) {
13366f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    struct sockaddr_in remoteAddr;
13376f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    socklen_t remoteAddrLen = sizeof(remoteAddr);
13386f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13396f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    int clientSocket = accept(
13406f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            s, (struct sockaddr *)&remoteAddr, &remoteAddrLen);
13416f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13426f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    if (clientSocket >= 0) {
13436f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                        status_t err = MakeSocketNonBlocking(clientSocket);
13446f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13456f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                        if (err != OK) {
13466f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            ALOGE("Unable to make client socket non blocking, "
13476f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                  "failed w/ error %d (%s)",
13486f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                  err, strerror(-err));
13496f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13506f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            close(clientSocket);
13516f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            clientSocket = -1;
13526f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                        } else {
13536f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            in_addr_t addr = ntohl(remoteAddr.sin_addr.s_addr);
13546f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13556f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            ALOGI("incoming connection from %d.%d.%d.%d:%d "
13566f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                  "(socket %d)",
13576f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                  (addr >> 24),
13586f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                  (addr >> 16) & 0xff,
13596f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                  (addr >> 8) & 0xff,
13606f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                  addr & 0xff,
13616f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                  ntohs(remoteAddr.sin_port),
13626f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                  clientSocket);
13636f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13646f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            sp<Session> clientSession =
13656f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                new Session(
13666f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                        mNextSessionID++,
13676f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                        Session::CONNECTED,
13686f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                        clientSocket,
13696f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                                        session->getNotificationMessage());
13706f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13718060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                            clientSession->setMode(
13728060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                                    session->isRTSPServer()
13738060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                                        ? Session::MODE_RTSP
13748060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber                                        : Session::MODE_DATAGRAM);
13757d34f83f64919295baff4b0e260267af3efb4f9fAndreas Huber
13766f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                            sessionsToAdd.push_back(clientSession);
13776f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                        }
13786f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    } else {
13796f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                        ALOGE("accept returned error %d (%s)",
13806f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                              errno, strerror(errno));
13816f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    }
13826f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                } else {
13836f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    status_t err = session->readMore();
13846f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    if (err != OK) {
1385a7f7e0ac9436a8417bb9f31aecedfec1909d4630Andreas Huber                        ALOGE("readMore on socket %d failed w/ error %d (%s)",
13866f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                              s, err, strerror(-err));
13876f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                    }
13886f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                }
13896f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            }
13906f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
13916f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            if (FD_ISSET(s, &ws)) {
13926f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                status_t err = session->writeMore();
13936f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                if (err != OK) {
1394a7f7e0ac9436a8417bb9f31aecedfec1909d4630Andreas Huber                    ALOGE("writeMore on socket %d failed w/ error %d (%s)",
13956f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                          s, err, strerror(-err));
13966f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber                }
13976f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            }
13986f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
13996f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
14006f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        while (!sessionsToAdd.empty()) {
14016f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            sp<Session> session = *sessionsToAdd.begin();
14026f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            sessionsToAdd.erase(sessionsToAdd.begin());
14036f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
14046f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            mSessions.add(session->sessionID(), session);
14056f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
14066f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber            ALOGI("added clientSession %d", session->sessionID());
14076f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber        }
14086f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber    }
14096f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}
14106f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
14116f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber}  // namespace android
14126f9aebc2da485775c7e8df2d5ac0a4e07c9978bfAndreas Huber
1413