shill: Splits the netlink message factory between message types.

Provides a mechanism to register message factories with
|NetlinkMessageFactory|.  Splits |NetlinkMessageFactory| into a generic
factory and one for |ControlNetlinkMessage| and |Nl80211Message|.  Uses
the registration mechanism to install the control and nl80211 message
factories.

This CL also moves |UnknownMessage| from being a subtype of
|Nl80211Message| to being a subtype of |NetlinkMessage|.

Lucy has some 'splaining to do: At startup time, the message type isn't
known for some types of netlink message (notably, the nl80211 class of
messages).  This message type is discovered, in the code, through the
|Config80211::AddFamilyByString| call.  This CL adds a message factory
closure to that call so that Config80211 can install the factory when
the code knows the message type against which to register the factory.

BUG=chromium:220372
TEST=unittest and manual (restarted shill with log=-10,wifi and observed
messages of all types being created for netlink messages coming from the
kernel).

Change-Id: I496b405c20ef98b6e23e96e8088fc542ff29264c
Reviewed-on: https://gerrit.chromium.org/gerrit/45314
Commit-Queue: Wade Guthrie <wdg@chromium.org>
Reviewed-by: Wade Guthrie <wdg@chromium.org>
Tested-by: Wade Guthrie <wdg@chromium.org>
diff --git a/nl80211_message.h b/nl80211_message.h
index 198b467..33b3dbc 100644
--- a/nl80211_message.h
+++ b/nl80211_message.h
@@ -181,6 +181,20 @@
   DISALLOW_COPY_AND_ASSIGN(OverrunMessage);
 };
 
+
+class UnknownMessage : public NetlinkMessage {
+ public:
+  UnknownMessage(uint16_t message_type, ByteString message_body) :
+      NetlinkMessage(message_type), message_body_(message_body) {}
+  virtual ByteString Encode(uint32_t sequence_number);
+  virtual void Print(int log_level) const;
+
+ private:
+  ByteString message_body_;
+
+  DISALLOW_COPY_AND_ASSIGN(UnknownMessage);
+};
+
 // Objects of the |GenericNetlinkMessage| type represent messages that contain
 // a |genlmsghdr| after a |nlmsghdr|.  These messages seem to all contain a
 // payload that consists of a list of structured attributes (it's possible that
@@ -265,6 +279,9 @@
       : GenericNetlinkMessage(kMessageType, command, command_string) {}
 
   virtual bool InitFromNlmsg(const nlmsghdr *msg);
+
+  // Message factory for all types of Control netlink message.
+  static NetlinkMessage *CreateMessage(const nlmsghdr *const_msg);
 };
 
 class NewFamilyMessage : public ControlNetlinkMessage {
@@ -340,6 +357,9 @@
   static std::string StringFromReason(uint16_t reason);
   static std::string StringFromStatus(uint16_t status);
 
+  // Message factory for all types of Nl80211 message.
+  static NetlinkMessage *CreateMessage(const nlmsghdr *const_msg);
+
  private:
   static std::map<uint16_t, std::string> *reason_code_string_;
   static std::map<uint16_t, std::string> *status_code_string_;
@@ -673,22 +693,6 @@
 };
 
 
-class UnknownMessage : public Nl80211Message {
- public:
-  explicit UnknownMessage(uint8_t command)
-      : Nl80211Message(command, kCommandString),
-        command_(command) {}
-
-  static const uint8_t kCommand;
-  static const char kCommandString[];
-
- private:
-  uint8_t command_;
-
-  DISALLOW_COPY_AND_ASSIGN(UnknownMessage);
-};
-
-
 class UnprotDeauthenticateMessage : public Nl80211Message {
  public:
   static const uint8_t kCommand;
@@ -720,18 +724,24 @@
 
 class NetlinkMessageFactory {
  public:
+  typedef base::Callback<NetlinkMessage *(const nlmsghdr *msg)> FactoryMethod;
+
+  NetlinkMessageFactory() {}
+
+  // Adds a message factory for a specific message_type.  Intended to be used
+  // at initialization.
+  bool AddFactoryMethod(uint16_t message_type, FactoryMethod factory);
+
   // Ownership of the message is passed to the caller and, as such, he should
   // delete it.
-  static NetlinkMessage *CreateMessage(nlmsghdr *msg);
-  // TODO(wdg): Need a way for a class to register a callback and a message
-  // type.  That way, CreateMessage can call the appropriate factory based on
-  // the incoming message type.
+  NetlinkMessage *CreateMessage(const nlmsghdr *msg) const;
 
  private:
+  std::map<uint16_t, FactoryMethod> factories_;
+
   DISALLOW_COPY_AND_ASSIGN(NetlinkMessageFactory);
 };
 
-
 // Nl80211MessageDataCollector - this class is used to collect data to be
 // used for unit tests.  It is only invoked in this case.