diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,23 @@
+Copyright (c) 2013 Marcos Pividori
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the
+Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions of
+the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Network/PushNotify/General.hs b/Network/PushNotify/General.hs
new file mode 100644
--- /dev/null
+++ b/Network/PushNotify/General.hs
@@ -0,0 +1,116 @@
+module Network.PushNotify.General
+    (
+    -- * The purpose of this library
+    -- $purpose
+    
+    -- * How to use this library
+    -- $explanation
+
+    -- * PushManager Subsite
+    -- $subsite
+   
+    -- * Push Service
+      startPushService
+    , closePushService
+    , sendPush
+    , withPushManager
+    -- * Push Manager
+    , PushManager
+    -- * Push Settings
+    , Device(..)
+    , PushServiceConfig(..)
+    , RegisterResult(..)
+    , PushConfig(..)
+    , GCMConfig(..)
+    -- * Push Message
+    , PushNotification(..)
+    , generalNotif
+    -- * Push Result
+    , PushResult(..)
+    ) where
+
+import Network.PushNotify.General.Send
+import Network.PushNotify.General.Types
+import Network.PushNotify.General.YesodPushApp
+
+-- $purpose
+-- This library defines a general API for communicating with iOS,
+-- Android and WPhone powered devices, sending/receiving Push Notifications.
+--
+-- The main idea is to hide as much as possible the differences between the different services.
+--
+-- Push Notification services in general, are very similar. They all are asynchronous, best-effort services
+-- that offer third-party developers a channel to send data to apps from a cloud service in a power-efficient manner.
+-- The main differences between them, refer to details as: the maxim payload length, the quality of service,
+-- queueing the messages or not, and the time limit for this, the way the messages are handled on devices, etc.
+--
+-- The registration of devices is very similar too. The device/app gets a unique ID provided by the different services,
+-- and sends this identifier to your 3rd party server.
+-- So then, when you want to send messages to these devices, you have to send them to the Push Servers, and
+-- they will deliver the messages to the proper devices.
+--
+-- So, 'Device' will be our general identifier.
+--
+
+-- $explanation
+-- All the communication with devices will be abstracted behind the 'PushManager' data type.
+--
+-- You will reference to it when intending to send notifications. Also, if you properly set the callback functions,
+-- you will be able to receive messages from devices.
+--
+-- So, the mains steps:
+--
+-- * First you establish the main configuration for the push service: 'PushServiceConfig' . This means, set the configurations for the
+-- different Push services you want to use, and also set the callbacks functions. These functions could be used to actualize a DB,
+-- do some processing in background, etc.
+--
+-- * Then you start the service with the 'startPushService' function and you get the 'PushManager'.
+--     So, you can add this subsite to your Yesod app or just ignore it if you don't want to receive messages from devices.
+--
+-- * When you want to send notifications:
+--
+--      (1) You have to specify the 'PushNotification' , setting the parameters. Here you have to do it
+--           for each kind of notification, because they contain different structures.
+--
+--      2. Then, you can send these with the 'sendPush' function, passing the 'PushManager' as an argument. Also, you can get useful information
+--           from the 'PushResult' value after communicating with servers.
+--
+-- * At the end, you stop the service with: 'closePushService'.
+--
+--
+-- When your Apps on devices need to send an upstream message they have 2 options:
+--
+--      (1) Messages through CCS (only Android devices).
+--         For this you have to set the proper CCS settings when starting the Push Service.
+--
+--      2. Messages as HTTP requests to 'PushManager' Yesod subsite (all devices).
+--         (using the route of the Yesod subsite: something like \".../messages\" )
+--
+-- You can see many test examples on the GitHub repository: <https://github.com/MarcosPividori/GSoC-Communicating-with-mobile-devices>
+
+-- $subsite
+-- Everytime a device sends a message to our system as HTTP POST request it should provide the pair
+-- {\"regId\" : identifier , \"system\" : system } specifing the ID and the system running on the device, so we can build 
+-- the 'Device' identifier.
+--
+-- Now we support APNS, MPNS and GCM. So the possible combinations are:
+--
+-- { \"regId\" : 'Network.PushNotify.Gcm.RegId' , \"system\" : \"ANDROID\" }
+--
+-- { \"regId\" : 'Network.PushNotify.Mpns.DeviceURI' , \"system\" : \"WPHONE\" }
+--
+-- { \"regId\" : 'Network.PushNotify.Apns.DeviceToken' , \"system\" : \"IOS\" } (token stored in hexadecimal representation)
+-- 
+-- This 'PushManager' Yesod subsite consists of 2 routes for receiving JSON data:
+--
+--  * /register -> this route will receive the registration from devices. So devices have to send the pairs
+--      {\"regId\" : identifier , \"system\" : system }  and any extra information. When a new intent for a registration arrives,
+--      the 'newDeviceCallback' function will be called with the identifier and JSON data as arguments so you can ask for more information
+--      as username and password, etc. Depending on the callback function result, the response to the POST request
+--      will be set, so device can know if it has successfully registered on the server.
+--
+--  *  /messages -> this route will receive POST messages from devices. Again, devices have to send the pairs
+--      {\"regId\" : identifier , \"system\" : system } and any other extra information.
+--      Everytime a new messages arrives to the Yesod subsite, the 'newMessageCallback' function will be called with the identifier
+--      and JSON data as arguments.
+--      This abstraction lets us use the same callback function to handle the messages that arrive from CCS too (XMPP connection for GCM).
diff --git a/Network/PushNotify/General/Send.hs b/Network/PushNotify/General/Send.hs
new file mode 100644
--- /dev/null
+++ b/Network/PushNotify/General/Send.hs
@@ -0,0 +1,132 @@
+-- | This Module define the main functions to send Push Notifications.
+{-# LANGUAGE ScopedTypeVariables #-}
+module Network.PushNotify.General.Send(
+    startPushService
+  , closePushService
+  , sendPush
+  , withPushManager
+  ) where
+
+import Network.PushNotify.General.Types
+import Network.PushNotify.General.YesodPushApp
+
+import Yesod
+import Data.Text                        (Text)
+import Data.Maybe
+import Data.Monoid
+import Data.Default
+import Control.Concurrent
+import Control.Monad
+import Control.Exception                as CE
+import qualified Data.HashMap.Strict    as HM
+import qualified Data.HashSet           as HS
+import Network.HTTP.Conduit
+import Network.PushNotify.Gcm
+import Network.PushNotify.Apns
+import Network.PushNotify.Mpns
+import Network.PushNotify.Ccs
+
+-- | 'startPushService' starts the PushService creating a PushManager.
+startPushService :: PushServiceConfig -> IO PushManager
+startPushService pConfig = do
+                let cnfg    = pushConfig pConfig
+                    gcmflag = case gcmConfig cnfg of
+                                Just (Http _) -> True
+                                _             -> False
+                httpMan <- if gcmflag || isJust (mpnsConfig cnfg)
+                             then do
+                                    m <- newManager def
+                                    return (Just m)
+                             else return Nothing
+                apnsMan <- case apnsConfig cnfg of
+                             Just cnf -> do
+                                    m <- startAPNS cnf
+                                    return (Just m)
+                             Nothing  -> return Nothing
+                ccsMan  <- case gcmConfig cnfg of
+                             Just (Ccs cnf) -> do
+                                    m <- startCCS cnf (\d -> (newMessageCallback pConfig) (GCM d))
+                                    return (Just m)
+                             _                    -> return Nothing
+                return $ PushManager httpMan apnsMan ccsMan pConfig
+
+-- | 'closePushService' stops the Push service.
+closePushService :: PushManager -> IO ()
+closePushService man = do
+                         case httpManager man of
+                             Just m -> closeManager m
+                             _      -> return ()
+                         case apnsManager man of
+                             Just m -> closeAPNS m
+                             _      -> return ()
+                         case ccsManager man of
+                             Just m -> closeCCS m
+                             _      -> return ()
+
+-- | 'withPushManager' creates a new manager, uses it in the provided function, and then releases it.
+withPushManager :: PushServiceConfig -> (PushManager -> IO a) -> IO a
+withPushManager confg fun = CE.bracket (startPushService confg) closePushService fun
+
+forgetConst :: Device -> Text
+forgetConst (GCM  x) = x
+forgetConst (APNS x) = x
+forgetConst (MPNS x) = x
+
+isGCM  (GCM  _) = True
+isGCM  _        = False
+
+isAPNS (APNS _) = True
+isAPNS _        = False
+
+isMPNS (MPNS _) = True
+isMPNS _        = False
+
+-- | 'sendPush' sends messages to the appropiate Push Servers.
+sendPush :: PushManager -> PushNotification -> HS.HashSet Device -> IO PushResult
+sendPush man notif devices = do
+    let gcmDevices  = HS.map forgetConst $ HS.filter isGCM  devices
+        apnsDevices = HS.map forgetConst $ HS.filter isAPNS devices
+        mpnsDevices = HS.map forgetConst $ HS.filter isMPNS devices
+        pConfig     = serviceConfig man
+        config      = pushConfig pConfig
+
+    r1 <- case (HS.null gcmDevices , gcmConfig config , gcmNotif  notif , httpManager man , ccsManager man) of
+              (False,Just (Ccs cnf),Just msg,_,Just m)   -> do
+                            let msg' = msg{registration_ids = gcmDevices}
+                            CE.catch (sendCCS' m msg')
+                              (\e -> let _ = e :: CE.SomeException in
+                                     case httpManager man of
+                                       Just hman -> sendGCM' hman def{apiKey = aPiKey cnf} msg'
+                                       _ -> return $ exceptionResult (HM.fromList $ map (\d -> (GCM d,Right e)) $
+                                                                      HS.toList $ registration_ids msg') )
+
+              (False,Just (Http cnf),Just msg,Just m,_ ) -> sendGCM' m cnf msg{registration_ids = gcmDevices}
+
+              _                                          -> return def
+
+    r2 <- case (HS.null apnsDevices , apnsNotif notif , apnsManager man) of
+              (False,Just msg,Just m) -> sendAPNS' m msg{deviceTokens = apnsDevices}
+              _                       -> return def
+
+    r3 <- case (HS.null mpnsDevices , mpnsConfig config , mpnsNotif notif , httpManager man) of
+              (False,Just cnf,Just msg,Just m) -> sendMPNS' m cnf msg{deviceURIs = mpnsDevices}
+              _                                -> return def
+
+    let res = r1 <> r2 <> r3
+
+    when (not $ HS.null $ unRegistered res) $ mapM_ (unRegisteredCallback pConfig) (HS.toList $ unRegistered res)
+
+    when (not $ HM.null $ newIds res)       $ mapM_ (newIdCallback        pConfig) (HM.toList $ newIds res)
+
+    return res
+
+    where
+      sendCCS'  a b   = sendCCS a b >>= return . toPushResult
+      sendMPNS' a b c = sendMPNS a b c >>= return . toPushResult
+      sendGCM'  a b c = CE.catch (sendGCM a b c >>= return . toPushResult)
+                        (\(e :: CE.SomeException) -> return $ exceptionResult ( HM.fromList $ map (\d -> (GCM d,Right e)) $ 
+                                                                                HS.toList $ registration_ids c))
+      sendAPNS' a b   = CE.catch (sendAPNS a b >>= return . toPushResult)
+                        (\(e :: CE.SomeException) -> return $ exceptionResult ( HM.fromList $ map (\d -> (APNS d,Right e)) $
+                                                                                HS.toList $ deviceTokens b))
+      exceptionResult l = PushResult HS.empty l HS.empty HS.empty HM.empty
diff --git a/Network/PushNotify/General/Types.hs b/Network/PushNotify/General/Types.hs
new file mode 100644
--- /dev/null
+++ b/Network/PushNotify/General/Types.hs
@@ -0,0 +1,200 @@
+{-# LANGUAGE OverloadedStrings , DeriveGeneric #-}
+-- | This Module defines the main data types for the Push Service.
+module Network.PushNotify.General.Types
+    ( -- * Push Settings     
+      Device(..)
+    , PushServiceConfig(..)
+    , RegisterResult(..)
+    , GCMConfig(..)
+    , PushConfig(..)
+      -- * Push Manager
+    , PushManager(..)
+      -- * Push Message
+    , PushNotification(..)
+    , generalNotif
+      -- * Push Result
+    , PushResult(..)
+    , IsPushResult(..)
+    ) where
+
+import Network.PushNotify.Gcm
+import Network.PushNotify.Apns
+import Network.PushNotify.Mpns
+import Network.PushNotify.Ccs
+import Network.HTTP.Conduit
+import Network.HTTP.Types.Status
+import Control.Exception
+
+import qualified Data.Map               as M
+import qualified Data.ByteString.Lazy   as BL
+import qualified Data.ByteString        as BS
+import qualified Data.Text.Encoding     as E
+import qualified Data.HashMap.Strict    as HM
+import qualified Data.HashSet           as HS
+import Data.Aeson
+import Data.Default
+import Data.Hashable
+import Data.List
+import Data.Monoid
+import Data.Text     (Text,pack)
+import Text.XML
+
+-- | Unique identifier of an app/device.
+data Device = GCM  RegId        -- ^ An Android app.
+            | APNS DeviceToken  -- ^ An iOS app.
+            | MPNS DeviceURI    -- ^ A WPhone app.
+            deriving (Show, Read, Eq)
+
+instance Hashable Device where
+     hashWithSalt s (GCM n)   = s `hashWithSalt`
+                                 (0::Int) `hashWithSalt` n
+     hashWithSalt s (MPNS n)  = s `hashWithSalt`
+                                 (1::Int) `hashWithSalt` n
+     hashWithSalt s (APNS n)  = s `hashWithSalt`
+                                 (2::Int) `hashWithSalt` n
+
+-- | General notification to be sent.
+data PushNotification = PushNotification {
+        apnsNotif :: Maybe APNSmessage
+    ,   gcmNotif  :: Maybe GCMmessage
+    ,   mpnsNotif :: Maybe MPNSmessage
+    } deriving Show
+
+instance Default PushNotification where
+    def = PushNotification Nothing Nothing Nothing
+
+-- | 'generalNotif' builds a general notification from JSON data.
+--
+-- If data length exceeds 256 bytes (max payload limit for APNS) it will fails.
+--
+-- For MPNS, data will be XML-labeled as \"jsonData\".
+generalNotif :: Object -> IO PushNotification
+generalNotif dat = do
+    let msg = PushNotification {
+            apnsNotif = Just def{ rest        = Just dat}
+        ,   gcmNotif  = Just def{ data_object = Just dat}
+        ,   mpnsNotif = Just def{ restXML     = Document (Prologue [] Nothing [])
+                                                         (Element (Name "jsonData" Nothing Nothing)
+                                                                 M.empty
+                                                                 [NodeContent $ E.decodeUtf8 $
+                                                                    BS.concat . BL.toChunks $ encode dat])
+                                                         []
+                                }
+        }
+    if ((BL.length . encode . apnsNotif) msg > 256)
+      then fail "Too long payload"
+      else return msg
+
+-- | Settings for GCM service.
+data GCMConfig = Http GCMHttpConfig | Ccs GCMCcsConfig
+
+-- | Main settings for the different Push Services. @Nothing@ means the service won't be used.
+data PushConfig = PushConfig{
+        gcmConfig  :: Maybe GCMConfig
+    ,   apnsConfig :: Maybe APNSConfig
+    ,   mpnsConfig :: Maybe MPNSConfig
+    }
+
+instance Default PushConfig where
+    def = PushConfig Nothing Nothing Nothing
+
+-- | 'RegisterResult' represents the result of a device attempting to register
+data RegisterResult = SuccessfulReg | ErrorReg Text
+
+-- | Main settings for the Push Service.
+data PushServiceConfig = PushServiceConfig {
+        pushConfig           :: PushConfig                   -- ^ Main configuration.
+    ,   newMessageCallback   :: Device -> Value -> IO ()     -- ^ The callback function to be called when receiving messages from devices
+                                                             -- (This means through the CCS connection or as POST requests
+                                                             -- to the Yesod subsite).
+    ,   newDeviceCallback    :: Device -> Value -> IO RegisterResult -- ^ The callback function to be called when
+                                                                     -- a new device try to register on server.
+    ,   unRegisteredCallback :: Device -> IO ()              -- ^ The callback function to be called when a device unregisters.
+    ,   newIdCallback        :: (Device,Device) -> IO ()     -- ^ The callback function to be called when a device's identifier changes.
+    }
+
+instance Default PushServiceConfig where
+    def = PushServiceConfig {
+        pushConfig           = def
+    ,   newMessageCallback   = \_ _ -> return ()
+    ,   newDeviceCallback    = \_ _ -> return SuccessfulReg
+    ,   unRegisteredCallback = \_ -> return ()
+    ,   newIdCallback        = \_ -> return ()
+    }
+
+-- | Main manager for the Push Service.
+--
+-- This 'PushManager' will be used to send notifications and also can be added as a subsite to a Yesod app
+-- in order to receive registrations and messages from devices as HTTP POST requests.
+data PushManager = PushManager {
+        httpManager    :: Maybe Manager       -- ^ Conduit manager for sending push notifications though POST requests.
+    ,   apnsManager    :: Maybe APNSManager   -- ^ Apns manager for sending push notifications though APNS servers.
+    ,   ccsManager     :: Maybe CCSManager    -- ^ Ccs manager for communicating with GCM through Cloud Connection Server.
+    ,   serviceConfig  :: PushServiceConfig   -- ^ Main configuration.
+    }
+
+-- | PushResult represents a general result after communicating with a Push Server.
+data PushResult = PushResult {
+        successful   :: HS.HashSet Device -- ^ Notifications that were successfully sent.
+    ,   failed       :: HM.HashMap Device (Either Text SomeException) -- ^ Notifications that were not successfully sent.
+    ,   toResend     :: HS.HashSet Device -- ^ Failed notifications that you need to resend,
+                                          -- because servers were not available or there was a problem with the connection.
+    ,   unRegistered :: HS.HashSet Device -- ^ Set of unregistered devices.
+    ,   newIds       :: HM.HashMap Device Device -- ^ Map of devices which have changed their identifiers. (old -> new)
+    } deriving Show
+
+instance Default PushResult where
+    def = PushResult HS.empty HM.empty HS.empty HS.empty HM.empty
+
+instance Monoid PushResult where
+    mempty = def
+    mappend (PushResult a1 b1 c1 d1 e1)
+            (PushResult a2 b2 c2 d2 e2) = PushResult (HS.union a1 a2)  (HM.union b1 b2)
+                                                     (HS.union  c1 c2) (HS.union  d1 d2) (HM.union e1 e2)
+
+-- | This class represent the translation from a specific service's result into a general Push result.
+class IsPushResult a where
+    toPushResult :: a -> PushResult
+
+
+instance IsPushResult GCMresult where
+    toPushResult r = def {
+        successful   = HS.map GCM $ HS.fromList $ HM.keys $ messagesIds r
+    ,   failed       = HM.fromList $ map (\(x,y) -> (GCM x,Left y)) (HM.toList $ errorRest r)
+                    <> map (\x -> (GCM x,Left "UnregisteredError")) (HS.toList $ errorUnRegistered r)
+                    <> map (\x -> (GCM x,Left "InternalError"))     (HS.toList $ errorToReSend     r)
+    ,   toResend     = HS.map GCM $ errorToReSend r
+    ,   unRegistered = HS.map GCM $ errorUnRegistered r <> (HS.fromList . HM.keys . errorRest) r
+    -- I decide to unregister all regId with error different to Unregistered or Unavailable. (errorRest)
+    -- Because these are non-recoverable error.
+    ,   newIds       = HM.fromList $ map (\(x,y) -> (GCM x,GCM y)) $ HM.toList $ newRegids r
+    }
+
+
+instance IsPushResult APNSresult where
+    toPushResult r = def {
+        successful   = HS.map APNS $ successfulTokens r
+    ,   failed       = HM.fromList $ map (\x -> (APNS x , Left "CommunicatingError")) $ HS.toList $ toReSendTokens r
+    ,   toResend     = HS.map APNS $ toReSendTokens r
+    }
+
+instance IsPushResult APNSFeedBackresult where
+    toPushResult r = def {
+        unRegistered = HS.fromList $ map APNS $ HM.keys $ unRegisteredTokens r
+    }
+
+
+instance IsPushResult MPNSresult where
+    toPushResult r = let (successList,failureList) = partition ((== Just Received) . notificationStatus . snd ) $ 
+                                                               HM.toList $ successfullResults r
+                     in def {
+        successful   = HS.fromList $ map (MPNS . fst) successList
+    ,   failed       = (HM.fromList $ map (\(x,y) -> (MPNS x , Right y)) (HM.toList $ errorException r))
+                    <> (HM.fromList $ map (\(x,y) -> (MPNS x , Left $ pack $ show $ notificationStatus y)) failureList)
+    ,   toResend     = HS.map MPNS . HS.fromList . HM.keys . HM.filter error500 $ errorException r
+    ,   unRegistered = HS.map MPNS . HS.fromList . HM.keys . HM.filter ((== Just Expired) . subscriptionStatus) $ successfullResults r
+    } where
+        error500 :: SomeException -> Bool
+        error500 e = case (fromException e) :: Maybe HttpException of
+                         Just (StatusCodeException status _ _) -> (statusCode status) >= 500
+                         _                                     -> False
diff --git a/Network/PushNotify/General/YesodPushApp.hs b/Network/PushNotify/General/YesodPushApp.hs
new file mode 100644
--- /dev/null
+++ b/Network/PushNotify/General/YesodPushApp.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE OverloadedStrings, TypeFamilies, TemplateHaskell, FlexibleInstances, MultiParamTypeClasses, FlexibleContexts, QuasiQuotes #-}
+-- | This Module defines the Yesod subsite to be used for the registration and reception of messages from devices.
+module Network.PushNotify.General.YesodPushApp(
+  PushManager(..)
+  ) where
+
+import Network.PushNotify.General.Types
+import Network.PushNotify.General.YesodPushAppRoutes
+import Yesod
+import Control.Concurrent
+import Data.Text
+import Data.Aeson
+import qualified Data.HashMap.Strict as HM
+
+instance (RenderMessage master FormMessage, Yesod master) => YesodSubDispatch PushManager (HandlerT master IO) where
+    yesodSubDispatch = $(mkYesodSubDispatch resourcesPushManager)
+
+-- 'postRegister' allows a mobile device to register. (JSON POST messages to '/register')
+postSubRegisterR :: (RenderMessage master FormMessage, Yesod master) => HandlerT PushManager (HandlerT master IO) ()
+postSubRegisterR = do
+    value  <- parseJsonBody_
+    case value of
+        Object v -> do
+                      iden <- lookForIdentifier v
+                      pushManager <- getYesod
+                      res <- liftIO $ (newDeviceCallback $ serviceConfig pushManager) iden value
+                      case res of
+                        SuccessfulReg -> sendResponse $ RepJson emptyContent -- successful registration.
+                        ErrorReg t    -> permissionDenied t                  -- error in registration.
+        _        -> invalidArgs []
+
+lookForIdentifier :: Object -> HandlerT PushManager (HandlerT master IO) Device
+lookForIdentifier v = do
+                    regId <- case (HM.lookup "regId" v) of
+                                 Just (String s) -> return s
+                                 _               -> invalidArgs []
+                    case (HM.lookup "system" v) of
+                      Just (String "ANDROID") -> return $ GCM  regId -- A Android device.
+                      Just (String "WPHONE")  -> return $ MPNS regId -- A WPhone device.
+                      Just (String "IOS")     -> return $ APNS regId -- A iOS device.
+                      _                       -> invalidArgs []
+
+-- 'postMessages' allows a mobile device to send a message. (JSON POST messages to '/messages')
+postSubMessagesR :: (RenderMessage master FormMessage, Yesod master) => HandlerT PushManager (HandlerT master IO) ()
+postSubMessagesR = do
+    value  <- parseJsonBody_
+    case value of
+        Object v -> do
+                      iden <- lookForIdentifier v
+                      pushManager <- getYesod
+                      liftIO $ forkIO $ (newMessageCallback $ serviceConfig pushManager) iden value
+                      sendResponse $ RepJson emptyContent
+        _        -> invalidArgs []
diff --git a/Network/PushNotify/General/YesodPushAppRoutes.hs b/Network/PushNotify/General/YesodPushAppRoutes.hs
new file mode 100644
--- /dev/null
+++ b/Network/PushNotify/General/YesodPushAppRoutes.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE OverloadedStrings, TypeFamilies, TemplateHaskell, QuasiQuotes #-}
+
+module Network.PushNotify.General.YesodPushAppRoutes where
+
+import Yesod
+import Network.PushNotify.General.Types
+import Control.Concurrent
+import Data.Text
+
+-- Yesod subsite to be used for the registration and reception of messages from devices.
+mkYesodSubData "PushManager" [parseRoutes|
+/register SubRegisterR POST
+/messages SubMessagesR POST
+|]
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/push-notify-general.cabal b/push-notify-general.cabal
new file mode 100644
--- /dev/null
+++ b/push-notify-general.cabal
@@ -0,0 +1,48 @@
+name:                push-notify-general
+version:             0.1.0.0
+synopsis:            A general library for sending/receiving push notif. through dif. services.
+
+description:         This library offers an API for sending/receiving notifications, and handling the registration of devices on the server.
+                     .
+                     It provides a general abstraction which can be used to communicate through different services as APNS, GCM, MPNS.
+                     .
+                     For more information and test examples: <http://gsoc2013cwithmobiledevices.blogspot.com.ar/>
+                     .
+                     GitHub repository: <https://github.com/MarcosPividori/GSoC-Communicating-with-mobile-devices>
+
+homepage:            http://gsoc2013cwithmobiledevices.blogspot.com.ar/
+license:             MIT
+license-file:        LICENSE
+author:              Marcos Pividori, mentored by Michael Snoyman.
+maintainer:          Marcos Pividori <marcos.pividori@gmail.com>
+
+category:            Network, Cloud, Mobile
+build-type:          Simple
+cabal-version:       >=1.8
+
+library
+  exposed-modules:   Network.PushNotify.General
+
+  other-modules:     Network.PushNotify.General.Send
+                   , Network.PushNotify.General.Types
+                   , Network.PushNotify.General.YesodPushApp
+                   , Network.PushNotify.General.YesodPushAppRoutes
+  
+  build-depends:     base                 >=4.5  && <5
+                   , aeson                >=0.6
+                   , bytestring           >=0.9
+                   , containers           >=0.4
+                   , data-default         >=0.5
+                   , hashable             >=1.2
+                   , http-conduit         >=1.9
+                   , http-types           >=0.8
+                   , push-notify          >=0.1
+                   , push-notify-ccs      >=0.1
+                   , text                 >=0.11
+                   , unordered-containers >=0.2
+                   , xml-conduit          >=1.1
+                   , yesod                >=1.2
+
+source-repository head
+  type:     git
+  location: https://github.com/MarcosPividori/GSoC-Communicating-with-mobile-devices.git
