libsysutils: Add iovec/runOnEachSocket

SocketClient:
* Replace sendDataLocked with sendDataLockedv which takes an iovec.
* Add a version of sendData, sendDatav, which takes an iovec.
* do not preserve iovec content through sendDatav

SocketListener:
* Add runOnEachSocket, which allows to to specify a SocketClientCommand to
  run individually on each socket. This allows you to do broadcast-like
  actions customized for each individual socket.
* Client safe list reference counting for sendBroadcast & runOnEach Socket

Signed-off-by: Nick Kralevich <nnk@google.com>
Signed-off-by: Mark Salyzyn <salyzyn@google.com>

Change-Id: I716f89c01b4cb7af900045c7e41fac1492defb06
diff --git a/include/sysutils/SocketClient.h b/include/sysutils/SocketClient.h
index 85b58ef..1004f06 100644
--- a/include/sysutils/SocketClient.h
+++ b/include/sysutils/SocketClient.h
@@ -6,22 +6,23 @@
 #include <pthread.h>
 #include <cutils/atomic.h>
 #include <sys/types.h>
+#include <sys/uio.h>
 
 class SocketClient {
     int             mSocket;
     bool            mSocketOwned;
     pthread_mutex_t mWriteMutex;
 
-    /* Peer process ID */
+    // Peer process ID
     pid_t mPid;
 
-    /* Peer user ID */
+    // Peer user ID
     uid_t mUid;
 
-    /* Peer group ID */
+    // Peer group ID
     gid_t mGid;
 
-    /* Reference count (starts at 1) */
+    // Reference count (starts at 1)
     pthread_mutex_t mRefCountMutex;
     int mRefCount;
 
@@ -38,12 +39,15 @@
     pid_t getPid() const { return mPid; }
     uid_t getUid() const { return mUid; }
     gid_t getGid() const { return mGid; }
-    void setCmdNum(int cmdNum) { android_atomic_release_store(cmdNum, &mCmdNum); }
+    void setCmdNum(int cmdNum) {
+        android_atomic_release_store(cmdNum, &mCmdNum);
+    }
     int getCmdNum() { return mCmdNum; }
 
     // Send null-terminated C strings:
     int sendMsg(int code, const char *msg, bool addErrno);
     int sendMsg(int code, const char *msg, bool addErrno, bool useCmdNum);
+    int sendMsg(const char *msg);
 
     // Provides a mechanism to send a response code to the client.
     // Sends the code and a null character.
@@ -56,6 +60,8 @@
 
     // Sending binary data:
     int sendData(const void *data, int len);
+    // iovec contents not preserved through call
+    int sendDatav(struct iovec *iov, int iovcnt);
 
     // Optional reference counting.  Reference count starts at 1.  If
     // it's decremented to 0, it deletes itself.
@@ -64,19 +70,18 @@
     void incRef();
     bool decRef(); // returns true at 0 (but note: SocketClient already deleted)
 
-    // return a new string in quotes with '\\' and '\"' escaped for "my arg" transmissions
+    // return a new string in quotes with '\\' and '\"' escaped for "my arg"
+    // transmissions
     static char *quoteArg(const char *arg);
 
 private:
-    // Send null-terminated C strings
-    int sendMsg(const char *msg);
     void init(int socket, bool owned, bool useCmdNum);
 
-    // Sending binary data. The caller should use make sure this is protected
+    // Sending binary data. The caller should make sure this is protected
     // from multiple threads entering simultaneously.
-    // returns 0 if successful, -1 if there is a 0 byte write and -2 if any other
-    // error occurred (use errno to get the error)
-    int sendDataLocked(const void *data, int len);
+    // returns 0 if successful, -1 if there is a 0 byte write or if any
+    // other error occurred (use errno to get the error)
+    int sendDataLockedv(struct iovec *iov, int iovcnt);
 };
 
 typedef android::sysutils::List<SocketClient *> SocketClientCollection;
diff --git a/include/sysutils/SocketClientCommand.h b/include/sysutils/SocketClientCommand.h
new file mode 100644
index 0000000..746bc25
--- /dev/null
+++ b/include/sysutils/SocketClientCommand.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _SOCKETCLIENTCOMMAND_H
+#define _SOCKETCLIENTCOMMAND_H
+
+#include <sysutils/SocketClient.h>
+
+class SocketClientCommand {
+public:
+    virtual ~SocketClientCommand() { }
+    virtual void runSocketCommand(SocketClient *client) = 0;
+};
+
+#endif
diff --git a/include/sysutils/SocketListener.h b/include/sysutils/SocketListener.h
index 8f56230..649c89a 100644
--- a/include/sysutils/SocketListener.h
+++ b/include/sysutils/SocketListener.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2008-2014 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
 #include <pthread.h>
 
 #include <sysutils/SocketClient.h>
+#include "SocketClientCommand.h"
 
 class SocketListener {
     bool                    mListen;
@@ -41,6 +42,8 @@
 
     void sendBroadcast(int code, const char *msg, bool addErrno);
 
+    void runOnEachSocket(SocketClientCommand *command);
+
 protected:
     virtual bool onDataAvailable(SocketClient *c) = 0;