• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/corennnnn


Commit MetaInfo

修订版fa644ffe944c01a9b00f8d7676d58394fabee285 (tree)
时间2009-05-11 01:26:42
作者San Mehat <san@goog...>
CommiterSan Mehat

Log Message

libsysutils: Add multiple client support and fix some bugs

更改概述

差异

--- /dev/null
+++ b/include/sysutils/FrameworkClient.h
@@ -0,0 +1,21 @@
1+#ifndef _FRAMEWORK_CLIENT_H
2+#define _FRAMEWORK_CLIENT_H
3+
4+#include "../../../frameworks/base/include/utils/List.h"
5+
6+#include <pthread.h>
7+
8+class FrameworkClient {
9+ int mSocket;
10+ pthread_mutex_t mWriteMutex;
11+
12+public:
13+ FrameworkClient(int sock);
14+ virtual ~FrameworkClient() {}
15+
16+ int sendMsg(char *msg);
17+ int sendMsg(char *msg, char *data);
18+};
19+
20+typedef android::List<FrameworkClient *> FrameworkClientCollection;
21+#endif
--- a/include/sysutils/FrameworkCommand.h
+++ b/include/sysutils/FrameworkCommand.h
@@ -18,6 +18,7 @@
1818
1919 #include "../../../frameworks/base/include/utils/List.h"
2020
21+class SocketClient;
2122
2223 class FrameworkCommand {
2324 private:
@@ -28,7 +29,7 @@ public:
2829 FrameworkCommand(const char *cmd);
2930 virtual ~FrameworkCommand() { }
3031
31- virtual int runCommand(char *data);
32+ virtual int runCommand(SocketClient *c, char *data) = 0;
3233
3334 const char *getCommand() { return mCommand; }
3435 };
--- a/include/sysutils/FrameworkListener.h
+++ b/include/sysutils/FrameworkListener.h
@@ -19,6 +19,8 @@
1919 #include "SocketListener.h"
2020 #include "FrameworkCommand.h"
2121
22+class SocketClient;
23+
2224 class FrameworkListener : public SocketListener {
2325 private:
2426 FrameworkCommandCollection *mCommands;
@@ -29,9 +31,9 @@ public:
2931
3032 protected:
3133 void registerCmd(FrameworkCommand *cmd);
32- virtual bool onDataAvailable(int socket);
34+ virtual bool onDataAvailable(SocketClient *c);
3335
3436 private:
35- void dispatchCommand(char *cmd);
37+ void dispatchCommand(SocketClient *c, char *cmd);
3638 };
3739 #endif
--- a/include/sysutils/FrameworkManager.h
+++ /dev/null
@@ -1,40 +0,0 @@
1-/*
2- * Copyright (C) 2008 The Android Open Source Project
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
15- */
16-#ifndef _FRAMEWORKMANAGER_H
17-#define _FRAMEWORKMANAGER_H
18-
19-#include <pthread.h>
20-
21-class FrameworkListener;
22-
23-class FrameworkManager {
24- int mDoorbell; // Socket used to accept connections from framework
25- int mFwSock; // Socket used to communicate with framework
26- const char *mSocketName;
27-
28- FrameworkListener *mListener;
29-
30- pthread_mutex_t mWriteMutex;
31-
32-public:
33- FrameworkManager(FrameworkListener *Listener);
34- virtual ~FrameworkManager() {}
35-
36- int run();
37- int sendMsg(char *msg);
38- int sendMsg(char *msg, char *data);
39-};
40-#endif
--- a/include/sysutils/NetlinkListener.h
+++ b/include/sysutils/NetlinkListener.h
@@ -27,6 +27,6 @@ public:
2727 NetlinkListener(int socket);
2828 virtual ~NetlinkListener() {}
2929 protected:
30- virtual bool onDataAvailable(int socket);
30+ virtual bool onDataAvailable(SocketClient *cli);
3131 };
3232 #endif
--- /dev/null
+++ b/include/sysutils/SocketClient.h
@@ -0,0 +1,23 @@
1+#ifndef _SOCKET_CLIENT_H
2+#define _SOCKET_CLIENT_H
3+
4+#include "../../../frameworks/base/include/utils/List.h"
5+
6+#include <pthread.h>
7+
8+class SocketClient {
9+ int mSocket;
10+ pthread_mutex_t mWriteMutex;
11+
12+public:
13+ SocketClient(int sock);
14+ virtual ~SocketClient() {}
15+
16+ int getSocket() { return mSocket; }
17+
18+ int sendMsg(char *msg);
19+ int sendMsg(char *msg, char *data);
20+};
21+
22+typedef android::List<SocketClient *> SocketClientCollection;
23+#endif
--- a/include/sysutils/SocketListener.h
+++ b/include/sysutils/SocketListener.h
@@ -16,20 +16,35 @@
1616 #ifndef _SOCKETLISTENER_H
1717 #define _SOCKETLISTENER_H
1818
19+#include <pthread.h>
20+
21+#include <sysutils/SocketClient.h>
22+
1923 class SocketListener {
20- int mSock;
21- int mCsock;
22- int mAcceptClients;
23- const char *mSocketName;
24+ int mSock;
25+ const char *mSocketName;
26+ SocketClientCollection *mClients;
27+ pthread_mutex_t mClientsLock;
28+ bool mListen;
29+ int mCtrlPipe[2];
30+ pthread_t mThread;
2431
2532 public:
26- SocketListener(const char *socketName, bool acceptClients);
27- SocketListener(int socketFd, bool acceptClients);
33+ SocketListener(const char *socketNames, bool listen);
34+ SocketListener(int socketFd, bool listen);
2835
2936 virtual ~SocketListener() {}
30- virtual int run();
37+ int startListener();
38+ int stopListener();
39+
40+ void sendBroadcast(char *msg);
41+ void sendBroadcast(char *msg, char *data);
3142
3243 protected:
33- virtual bool onDataAvailable(int socket);
44+ virtual bool onDataAvailable(SocketClient *c) = 0;
45+
46+private:
47+ static void *threadStart(void *obj);
48+ void runListener();
3449 };
3550 #endif
--- a/libsysutils/Android.mk
+++ b/libsysutils/Android.mk
@@ -3,12 +3,12 @@ LOCAL_PATH:= $(call my-dir)
33 include $(CLEAR_VARS)
44
55 LOCAL_SRC_FILES:= \
6- src/FrameworkManager.cpp \
76 src/SocketListener.cpp \
87 src/FrameworkListener.cpp \
98 src/NetlinkListener.cpp \
109 src/NetlinkEvent.cpp \
1110 src/FrameworkCommand.cpp \
11+ src/SocketClient.cpp \
1212
1313 LOCAL_MODULE:= libsysutils
1414
--- /dev/null
+++ b/libsysutils/src/FrameworkClient.cpp
@@ -0,0 +1,41 @@
1+#include <alloca.h>
2+#include <errno.h>
3+#include <sys/types.h>
4+#include <pthread.h>
5+
6+#define LOG_TAG "FrameworkClient"
7+#include <cutils/log.h>
8+
9+#include <sysutils/FrameworkClient.h>
10+
11+FrameworkClient::FrameworkClient(int socket) {
12+ mSocket = socket;
13+ pthread_mutex_init(&mWriteMutex, NULL);
14+}
15+
16+int FrameworkClient::sendMsg(char *msg) {
17+ LOGD("FrameworkClient::sendMsg(%s)", msg);
18+ if (mSocket < 0) {
19+ errno = EHOSTUNREACH;
20+ return -1;
21+ }
22+
23+ pthread_mutex_lock(&mWriteMutex);
24+ if (write(mSocket, msg, strlen(msg) +1) < 0) {
25+ LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno));
26+ }
27+ pthread_mutex_unlock(&mWriteMutex);
28+ return 0;
29+}
30+
31+int FrameworkClient::sendMsg(char *msg, char *data) {
32+ char *buffer = (char *) alloca(strlen(msg) + strlen(data) + 1);
33+ if (!buffer) {
34+ errno = -ENOMEM;
35+ return -1;
36+ }
37+ strcpy(buffer, msg);
38+ strcat(buffer, data);
39+ return sendMsg(buffer);
40+}
41+
--- a/libsysutils/src/FrameworkCommand.cpp
+++ b/libsysutils/src/FrameworkCommand.cpp
@@ -25,7 +25,7 @@ FrameworkCommand::FrameworkCommand(const char *cmd) {
2525 mCommand = cmd;
2626 }
2727
28-int FrameworkCommand::runCommand(char *data) {
28+int FrameworkCommand::runCommand(SocketClient *c, char *data) {
2929 LOGW("Command %s has no run handler!", getCommand());
3030 errno = ENOSYS;
3131 return -1;
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -22,17 +22,18 @@
2222
2323 #include <sysutils/FrameworkListener.h>
2424 #include <sysutils/FrameworkCommand.h>
25+#include <sysutils/SocketClient.h>
2526
2627 FrameworkListener::FrameworkListener(const char *socketName) :
2728 SocketListener(socketName, true) {
2829 mCommands = new FrameworkCommandCollection();
2930 }
3031
31-bool FrameworkListener::onDataAvailable(int socket) {
32+bool FrameworkListener::onDataAvailable(SocketClient *c) {
3233 char buffer[101];
3334 int len;
3435
35- if ((len = read(socket, buffer, sizeof(buffer) -1)) < 0) {
36+ if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) {
3637 LOGE("read() failed (%s)", strerror(errno));
3738 return errno;
3839 } else if (!len) {
@@ -47,7 +48,7 @@ bool FrameworkListener::onDataAvailable(int socket) {
4748
4849 for (i = 0; i < len; i++) {
4950 if (buffer[i] == '\0') {
50- dispatchCommand(buffer + start);
51+ dispatchCommand(c, buffer + start);
5152 start = i + 1;
5253 }
5354 }
@@ -58,14 +59,22 @@ void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
5859 mCommands->push_back(cmd);
5960 }
6061
61-void FrameworkListener::dispatchCommand(char *cmd) {
62+void FrameworkListener::dispatchCommand(SocketClient *cli, char *cmd) {
63+
64+ char *cm, *last;
65+
66+ if (!(cm = strtok_r(cmd, ":", &last))) {
67+ cli->sendMsg("BAD_MSG");
68+ return;
69+ }
70+
6271 FrameworkCommandCollection::iterator i;
6372
6473 for (i = mCommands->begin(); i != mCommands->end(); ++i) {
6574 FrameworkCommand *c = *i;
6675
67- if (!strncmp(cmd, c->getCommand(), strlen(c->getCommand()))) {
68- if (c->runCommand(cmd)) {
76+ if (!strcmp(cm, c->getCommand())) {
77+ if (c->runCommand(cli, cmd)) {
6978 LOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
7079 }
7180 return;
@@ -73,5 +82,6 @@ void FrameworkListener::dispatchCommand(char *cmd) {
7382 }
7483
7584 LOGE("No cmd handlers defined for '%s'", cmd);
85+ cli->sendMsg("UNKNOWN_CMD");
86+ return;
7687 }
77-
--- a/libsysutils/src/FrameworkManager.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
1-/*
2- * Copyright (C) 2008 The Android Open Source Project
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
15- */
16-#include <stdio.h>
17-#include <errno.h>
18-#include <stdlib.h>
19-#include <sys/socket.h>
20-#include <sys/select.h>
21-#include <sys/time.h>
22-#include <sys/types.h>
23-#include <sys/un.h>
24-
25-#include <cutils/config_utils.h>
26-#include <cutils/cpu_info.h>
27-#include <cutils/properties.h>
28-#include <cutils/sockets.h>
29-
30-#define LOG_TAG "FrameworkManager"
31-#include <cutils/log.h>
32-
33-#include <sysutils/FrameworkManager.h>
34-#include <sysutils/FrameworkListener.h>
35-
36-FrameworkManager::FrameworkManager(FrameworkListener *Listener) {
37- mDoorbell = -1;
38- mFwSock = -1;
39- mListener = Listener;
40-
41- pthread_mutex_init(&mWriteMutex, NULL);
42-}
43-
44-int FrameworkManager::run() {
45-
46- if (mListener->run()) {
47- LOGE("Error running listener (%s)", strerror(errno));
48- return -1;
49- }
50-
51- return 0;
52-}
53-
54-/* ========
55- * Privates
56- * ========
57- */
58-
59-int FrameworkManager::sendMsg(char *msg) {
60- LOGD("FrameworkManager::sendMsg(%s)", msg);
61- if (mFwSock < 0) {
62- errno = EHOSTUNREACH;
63- return -1;
64- }
65-
66- pthread_mutex_lock(&mWriteMutex);
67- if (write(mFwSock, msg, strlen(msg) +1) < 0) {
68- LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno));
69- }
70- pthread_mutex_unlock(&mWriteMutex);
71- return 0;
72-}
73-
74-int FrameworkManager::sendMsg(char *msg, char *data) {
75- char *buffer = (char *) alloca(strlen(msg) + strlen(data) + 1);
76- if (!buffer) {
77- errno = -ENOMEM;
78- return -1;
79- }
80- strcpy(buffer, msg);
81- strcat(buffer, data);
82- return sendMsg(buffer);
83-}
--- a/libsysutils/src/NetlinkListener.cpp
+++ b/libsysutils/src/NetlinkListener.cpp
@@ -29,8 +29,9 @@ NetlinkListener::NetlinkListener(int socket) :
2929 SocketListener(socket, false) {
3030 }
3131
32-bool NetlinkListener::onDataAvailable(int socket)
32+bool NetlinkListener::onDataAvailable(SocketClient *cli)
3333 {
34+ int socket = cli->getSocket();
3435 LOGD("NetlinkListener::onDataAvailable()");
3536
3637 int count;
--- /dev/null
+++ b/libsysutils/src/SocketClient.cpp
@@ -0,0 +1,41 @@
1+#include <alloca.h>
2+#include <errno.h>
3+#include <sys/types.h>
4+#include <pthread.h>
5+
6+#define LOG_TAG "SocketClient"
7+#include <cutils/log.h>
8+
9+#include <sysutils/SocketClient.h>
10+
11+SocketClient::SocketClient(int socket) {
12+ mSocket = socket;
13+ pthread_mutex_init(&mWriteMutex, NULL);
14+}
15+
16+int SocketClient::sendMsg(char *msg) {
17+ LOGD("SocketClient::sendMsg(%s)", msg);
18+ if (mSocket < 0) {
19+ errno = EHOSTUNREACH;
20+ return -1;
21+ }
22+
23+ pthread_mutex_lock(&mWriteMutex);
24+ if (write(mSocket, msg, strlen(msg) +1) < 0) {
25+ LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno));
26+ }
27+ pthread_mutex_unlock(&mWriteMutex);
28+ return 0;
29+}
30+
31+int SocketClient::sendMsg(char *msg, char *data) {
32+ char *buffer = (char *) alloca(strlen(msg) + strlen(data) + 1);
33+ if (!buffer) {
34+ errno = -ENOMEM;
35+ return -1;
36+ }
37+ strcpy(buffer, msg);
38+ strcat(buffer, data);
39+ return sendMsg(buffer);
40+}
41+
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -24,26 +24,28 @@
2424
2525 #define LOG_TAG "SocketListener"
2626 #include <cutils/log.h>
27-
2827 #include <cutils/sockets.h>
2928
3029 #include <sysutils/SocketListener.h>
30+#include <sysutils/SocketClient.h>
3131
32-SocketListener::SocketListener(const char *socketName, bool acceptClients) {
33- mAcceptClients = acceptClients;
34- mCsock = -1;
32+SocketListener::SocketListener(const char *socketName, bool listen) {
33+ mListen = listen;
3534 mSocketName = socketName;
3635 mSock = -1;
36+ pthread_mutex_init(&mClientsLock, NULL);
37+ mClients = new SocketClientCollection();
3738 }
3839
39-SocketListener::SocketListener(int socketFd, bool acceptClients) {
40- mAcceptClients = acceptClients;
41- mCsock = -1;
40+SocketListener::SocketListener(int socketFd, bool listen) {
41+ mListen = listen;
4242 mSocketName = NULL;
4343 mSock = socketFd;
44+ pthread_mutex_init(&mClientsLock, NULL);
45+ mClients = new SocketClientCollection();
4446 }
4547
46-int SocketListener::run() {
48+int SocketListener::startListener() {
4749
4850 if (!mSocketName && mSock == -1) {
4951 errno = EINVAL;
@@ -56,72 +58,155 @@ int SocketListener::run() {
5658 }
5759 }
5860
59- if (mAcceptClients) {
60- if (listen(mSock, 4) < 0) {
61- LOGE("Unable to listen on socket (%s)", strerror(errno));
62- return -1;
63- }
61+ if (mListen && listen(mSock, 4) < 0) {
62+ LOGE("Unable to listen on socket (%s)", strerror(errno));
63+ return -1;
64+ } else if (!mListen) {
65+ mClients->push_back(new SocketClient(mSock));
66+ LOGD("Created phantom client");
6467 }
6568
69+ if (pipe(mCtrlPipe))
70+ return -1;
71+
72+ if (pthread_create(&mThread, NULL, SocketListener::threadStart, this))
73+ return -1;
74+
75+ return 0;
76+}
77+
78+int SocketListener::stopListener() {
79+ char c = 0;
80+
81+ if (write(mCtrlPipe[1], &c, 1) != 1) {
82+ LOGE("Error writing to control pipe (%s)", strerror(errno));
83+ return -1;
84+ }
85+
86+ LOGD("Signaled listener thread - waiting for it to die");
87+ void *ret;
88+ if (pthread_join(mThread, &ret)) {
89+ LOGE("Error joining to listener thread (%s)", strerror(errno));
90+ return -1;
91+ }
92+ LOGD("Listener stopped");
93+ return 0;
94+}
95+
96+void *SocketListener::threadStart(void *obj) {
97+ SocketListener *me = reinterpret_cast<SocketListener *>(obj);
98+
99+ me->runListener();
100+ LOGD("Listener thread shutting down");
101+ pthread_exit(NULL);
102+ return NULL;
103+}
104+
105+void SocketListener::runListener() {
106+
66107 while(1) {
108+ SocketClientCollection::iterator it;
67109 fd_set read_fds;
68110 struct timeval to;
69- int max = 0;
70111 int rc = 0;
71112
72113 to.tv_sec = 60 * 60;
73114 to.tv_usec = 0;
74115
116+ int max = 0;
117+
75118 FD_ZERO(&read_fds);
76119
77- if ((mAcceptClients == false) ||
78- (mAcceptClients == true && mCsock == -1)) {
79- FD_SET(mSock, &read_fds);
120+ if (mListen) {
80121 max = mSock;
81- } else if (mCsock != -1) {
82- FD_SET(mCsock, &read_fds);
83- max = mCsock;
122+ FD_SET(mSock, &read_fds);
84123 }
85124
125+ FD_SET(mCtrlPipe[0], &read_fds);
126+ if (mCtrlPipe[0] > max)
127+ max = mCtrlPipe[0];
128+
129+ pthread_mutex_lock(&mClientsLock);
130+ for (it = mClients->begin(); it != mClients->end(); ++it) {
131+ FD_SET((*it)->getSocket(), &read_fds);
132+ if ((*it)->getSocket() > max)
133+ max = (*it)->getSocket();
134+ }
135+ pthread_mutex_unlock(&mClientsLock);
136+
86137 if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) {
87138 LOGE("select failed (%s)", strerror(errno));
88- return -errno;
89- } else if (!rc)
139+ sleep(1);
90140 continue;
91- else if (FD_ISSET(mSock, &read_fds)) {
92- /*
93- * If we're accepting client connections then
94- * accept and gobble the event. Otherwise
95- * pass it on to the handlers.
96- */
97- if (mAcceptClients) {
98- struct sockaddr addr;
99- socklen_t alen = sizeof(addr);
100-
101- if ((mCsock = accept(mSock, &addr, &alen)) < 0) {
102- LOGE("accept failed (%s)", strerror(errno));
103- return -errno;
104- }
105- LOGD("SocketListener client connection accepted");
106- } else if (!onDataAvailable(mSock)) {
107- LOGW("SocketListener closing listening socket (Will shut down)");
108- close(mSock);
109- return -ESHUTDOWN;
141+ } else if (!rc) {
142+ LOGD("select timeout");
143+ continue;
144+ }
145+
146+ if (FD_ISSET(mCtrlPipe[0], &read_fds)) {
147+ LOGD("Control message received");
148+ break;
149+ }
150+ if (mListen && FD_ISSET(mSock, &read_fds)) {
151+ struct sockaddr addr;
152+ socklen_t alen = sizeof(addr);
153+ int c;
154+
155+ if ((c = accept(mSock, &addr, &alen)) < 0) {
156+ LOGE("accept failed (%s)", strerror(errno));
157+ sleep(1);
158+ continue;
110159 }
111- } else if ((FD_ISSET(mCsock, &read_fds)) &&
112- !onDataAvailable(mCsock)) {
113- /*
114- * Once mCsock == -1, we'll start
115- * accepting connections on mSock again.
116- */
117- LOGD("SocketListener closing client socket");
118- close(mCsock);
119- mCsock = -1;
160+ LOGD("SocketListener client connection accepted");
161+ pthread_mutex_lock(&mClientsLock);
162+ mClients->push_back(new SocketClient(c));
163+ pthread_mutex_unlock(&mClientsLock);
164+ }
165+
166+ do {
167+ pthread_mutex_lock(&mClientsLock);
168+ for (it = mClients->begin(); it != mClients->end(); ++it) {
169+ int fd = (*it)->getSocket();
170+ if (FD_ISSET(fd, &read_fds)) {
171+ pthread_mutex_unlock(&mClientsLock);
172+ if (!onDataAvailable(*it)) {
173+ LOGD("SocketListener closing client socket");
174+ close(fd);
175+ pthread_mutex_lock(&mClientsLock);
176+ delete *it;
177+ it = mClients->erase(it);
178+ pthread_mutex_unlock(&mClientsLock);
179+ }
180+ FD_CLR(fd, &read_fds);
181+ continue;
182+ }
120183 }
184+ pthread_mutex_unlock(&mClientsLock);
185+ } while (0);
121186 }
122- return 0;
123187 }
124188
125-bool SocketListener::onDataAvailable(int socket) {
126- return false;
189+void SocketListener::sendBroadcast(char *msg) {
190+ pthread_mutex_lock(&mClientsLock);
191+ SocketClientCollection::iterator i;
192+
193+ for (i = mClients->begin(); i != mClients->end(); ++i) {
194+ if ((*i)->sendMsg(msg)) {
195+ LOGW("Error sending broadcast (%s)", strerror(errno));
196+ }
197+ }
198+ pthread_mutex_unlock(&mClientsLock);
199+}
200+
201+void SocketListener::sendBroadcast(char *msg, char *data) {
202+ pthread_mutex_lock(&mClientsLock);
203+ SocketClientCollection::iterator i;
204+
205+ for (i = mClients->begin(); i != mClients->end(); ++i) {
206+ if ((*i)->sendMsg(msg, data)) {
207+ LOGW("Error sending broadcast (%s)", strerror(errno));
208+ }
209+ }
210+ pthread_mutex_unlock(&mClientsLock);
127211 }
212+