{- | Copyright : Will Thompson, Iñaki García Etxebarria and Jonas Platte License : LGPL-2.1 Maintainer : Iñaki García Etxebarria (inaki@blueleaf.cc) A 'GI.Gio.Objects.SocketService.SocketService' is an object that represents a service that is provided to the network or over local sockets. When a new connection is made to the service the 'GI.Gio.Objects.SocketService.SocketService'::@/incoming/@ signal is emitted. A 'GI.Gio.Objects.SocketService.SocketService' is a subclass of 'GI.Gio.Objects.SocketListener.SocketListener' and you need to add the addresses you want to accept connections on with the 'GI.Gio.Objects.SocketListener.SocketListener' APIs. There are two options for implementing a network service based on 'GI.Gio.Objects.SocketService.SocketService'. The first is to create the service using 'GI.Gio.Objects.SocketService.socketServiceNew' and to connect to the 'GI.Gio.Objects.SocketService.SocketService'::@/incoming/@ signal. The second is to subclass 'GI.Gio.Objects.SocketService.SocketService' and override the default signal handler implementation. In either case, the handler must immediately return, or else it will block additional incoming connections from being serviced. If you are interested in writing connection handlers that contain blocking code then see 'GI.Gio.Objects.ThreadedSocketService.ThreadedSocketService'. The socket service runs on the main loop of the [thread-default context][g-main-context-push-thread-default-context] of the thread it is created in, and is not threadsafe in general. However, the calls to start and stop the service are thread-safe so these can be used from threads that handle incoming clients. /Since: 2.22/ -} #define ENABLE_OVERLOADING (MIN_VERSION_haskell_gi_overloading(1,0,0) \ && !defined(__HADDOCK_VERSION__)) module GI.Gio.Objects.SocketService ( -- * Exported types SocketService(..) , IsSocketService , toSocketService , noSocketService , -- * Methods -- ** isActive #method:isActive# #if ENABLE_OVERLOADING SocketServiceIsActiveMethodInfo , #endif socketServiceIsActive , -- ** new #method:new# socketServiceNew , -- ** start #method:start# #if ENABLE_OVERLOADING SocketServiceStartMethodInfo , #endif socketServiceStart , -- ** stop #method:stop# #if ENABLE_OVERLOADING SocketServiceStopMethodInfo , #endif socketServiceStop , -- * Properties -- ** active #attr:active# {- | Whether the service is currently accepting connections. /Since: 2.46/ -} #if ENABLE_OVERLOADING SocketServiceActivePropertyInfo , #endif constructSocketServiceActive , getSocketServiceActive , setSocketServiceActive , #if ENABLE_OVERLOADING socketServiceActive , #endif -- * Signals -- ** incoming #signal:incoming# C_SocketServiceIncomingCallback , SocketServiceIncomingCallback , #if ENABLE_OVERLOADING SocketServiceIncomingSignalInfo , #endif afterSocketServiceIncoming , genClosure_SocketServiceIncoming , mk_SocketServiceIncomingCallback , noSocketServiceIncomingCallback , onSocketServiceIncoming , wrap_SocketServiceIncomingCallback , ) where import Data.GI.Base.ShortPrelude import qualified Data.GI.Base.ShortPrelude as SP import qualified Data.GI.Base.Overloading as O import qualified Prelude as P import qualified Data.GI.Base.Attributes as GI.Attributes import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr import qualified Data.GI.Base.GClosure as B.GClosure import qualified Data.GI.Base.GError as B.GError import qualified Data.GI.Base.GVariant as B.GVariant import qualified Data.GI.Base.GValue as B.GValue import qualified Data.GI.Base.GParamSpec as B.GParamSpec import qualified Data.GI.Base.CallStack as B.CallStack import qualified Data.GI.Base.Properties as B.Properties import qualified Data.Text as T import qualified Data.ByteString.Char8 as B import qualified Data.Map as Map import qualified Foreign.Ptr as FP import qualified GHC.OverloadedLabels as OL import qualified GI.GObject.Objects.Object as GObject.Object import {-# SOURCE #-} qualified GI.Gio.Objects.SocketConnection as Gio.SocketConnection import {-# SOURCE #-} qualified GI.Gio.Objects.SocketListener as Gio.SocketListener -- | Memory-managed wrapper type. newtype SocketService = SocketService (ManagedPtr SocketService) foreign import ccall "g_socket_service_get_type" c_g_socket_service_get_type :: IO GType instance GObject SocketService where gobjectType = c_g_socket_service_get_type -- | Type class for types which can be safely cast to `SocketService`, for instance with `toSocketService`. class (GObject o, O.IsDescendantOf SocketService o) => IsSocketService o instance (GObject o, O.IsDescendantOf SocketService o) => IsSocketService o instance O.HasParentTypes SocketService type instance O.ParentTypes SocketService = '[Gio.SocketListener.SocketListener, GObject.Object.Object] -- | Cast to `SocketService`, for types for which this is known to be safe. For general casts, use `Data.GI.Base.ManagedPtr.castTo`. toSocketService :: (MonadIO m, IsSocketService o) => o -> m SocketService toSocketService = liftIO . unsafeCastTo SocketService -- | A convenience alias for `Nothing` :: `Maybe` `SocketService`. noSocketService :: Maybe SocketService noSocketService = Nothing #if ENABLE_OVERLOADING type family ResolveSocketServiceMethod (t :: Symbol) (o :: *) :: * where ResolveSocketServiceMethod "accept" o = Gio.SocketListener.SocketListenerAcceptMethodInfo ResolveSocketServiceMethod "acceptAsync" o = Gio.SocketListener.SocketListenerAcceptAsyncMethodInfo ResolveSocketServiceMethod "acceptFinish" o = Gio.SocketListener.SocketListenerAcceptFinishMethodInfo ResolveSocketServiceMethod "acceptSocket" o = Gio.SocketListener.SocketListenerAcceptSocketMethodInfo ResolveSocketServiceMethod "acceptSocketAsync" o = Gio.SocketListener.SocketListenerAcceptSocketAsyncMethodInfo ResolveSocketServiceMethod "acceptSocketFinish" o = Gio.SocketListener.SocketListenerAcceptSocketFinishMethodInfo ResolveSocketServiceMethod "addAddress" o = Gio.SocketListener.SocketListenerAddAddressMethodInfo ResolveSocketServiceMethod "addAnyInetPort" o = Gio.SocketListener.SocketListenerAddAnyInetPortMethodInfo ResolveSocketServiceMethod "addInetPort" o = Gio.SocketListener.SocketListenerAddInetPortMethodInfo ResolveSocketServiceMethod "addSocket" o = Gio.SocketListener.SocketListenerAddSocketMethodInfo ResolveSocketServiceMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo ResolveSocketServiceMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo ResolveSocketServiceMethod "close" o = Gio.SocketListener.SocketListenerCloseMethodInfo ResolveSocketServiceMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo ResolveSocketServiceMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo ResolveSocketServiceMethod "getv" o = GObject.Object.ObjectGetvMethodInfo ResolveSocketServiceMethod "isActive" o = SocketServiceIsActiveMethodInfo ResolveSocketServiceMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo ResolveSocketServiceMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo ResolveSocketServiceMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo ResolveSocketServiceMethod "ref" o = GObject.Object.ObjectRefMethodInfo ResolveSocketServiceMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo ResolveSocketServiceMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo ResolveSocketServiceMethod "start" o = SocketServiceStartMethodInfo ResolveSocketServiceMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo ResolveSocketServiceMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo ResolveSocketServiceMethod "stop" o = SocketServiceStopMethodInfo ResolveSocketServiceMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo ResolveSocketServiceMethod "unref" o = GObject.Object.ObjectUnrefMethodInfo ResolveSocketServiceMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo ResolveSocketServiceMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo ResolveSocketServiceMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo ResolveSocketServiceMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo ResolveSocketServiceMethod "setBacklog" o = Gio.SocketListener.SocketListenerSetBacklogMethodInfo ResolveSocketServiceMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo ResolveSocketServiceMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo ResolveSocketServiceMethod l o = O.MethodResolutionFailed l o instance (info ~ ResolveSocketServiceMethod t SocketService, O.MethodInfo info SocketService p) => OL.IsLabel t (SocketService -> p) where #if MIN_VERSION_base(4,10,0) fromLabel = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info) #else fromLabel _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info) #endif #endif -- signal SocketService::incoming {- | The ::incoming signal is emitted when a new incoming connection to /@service@/ needs to be handled. The handler must initiate the handling of /@connection@/, but may not block; in essence, asynchronous operations must be used. /@connection@/ will be unreffed once the signal handler returns, so you need to ref it yourself if you are planning to use it. /Since: 2.22/ -} type SocketServiceIncomingCallback = Gio.SocketConnection.SocketConnection {- ^ /@connection@/: a new 'GI.Gio.Objects.SocketConnection.SocketConnection' object -} -> Maybe GObject.Object.Object {- ^ /@sourceObject@/: the source_object passed to 'GI.Gio.Objects.SocketListener.socketListenerAddAddress' -} -> IO Bool {- ^ __Returns:__ 'True' to stop other handlers from being called -} -- | A convenience synonym for @`Nothing` :: `Maybe` `SocketServiceIncomingCallback`@. noSocketServiceIncomingCallback :: Maybe SocketServiceIncomingCallback noSocketServiceIncomingCallback = Nothing -- | Type for the callback on the (unwrapped) C side. type C_SocketServiceIncomingCallback = Ptr () -> -- object Ptr Gio.SocketConnection.SocketConnection -> Ptr GObject.Object.Object -> Ptr () -> -- user_data IO CInt -- | Generate a function pointer callable from C code, from a `C_SocketServiceIncomingCallback`. foreign import ccall "wrapper" mk_SocketServiceIncomingCallback :: C_SocketServiceIncomingCallback -> IO (FunPtr C_SocketServiceIncomingCallback) -- | Wrap the callback into a `GClosure`. genClosure_SocketServiceIncoming :: MonadIO m => SocketServiceIncomingCallback -> m (GClosure C_SocketServiceIncomingCallback) genClosure_SocketServiceIncoming cb = liftIO $ do let cb' = wrap_SocketServiceIncomingCallback cb mk_SocketServiceIncomingCallback cb' >>= B.GClosure.newGClosure -- | Wrap a `SocketServiceIncomingCallback` into a `C_SocketServiceIncomingCallback`. wrap_SocketServiceIncomingCallback :: SocketServiceIncomingCallback -> C_SocketServiceIncomingCallback wrap_SocketServiceIncomingCallback _cb _ connection sourceObject _ = do connection' <- (newObject Gio.SocketConnection.SocketConnection) connection maybeSourceObject <- if sourceObject == nullPtr then return Nothing else do sourceObject' <- (newObject GObject.Object.Object) sourceObject return $ Just sourceObject' result <- _cb connection' maybeSourceObject let result' = (fromIntegral . fromEnum) result return result' {- | Connect a signal handler for the “@incoming@” signal, to be run before the default handler. When is enabled, this is equivalent to @ 'Data.GI.Base.Signals.on' socketService #incoming callback @ -} onSocketServiceIncoming :: (IsSocketService a, MonadIO m) => a -> SocketServiceIncomingCallback -> m SignalHandlerId onSocketServiceIncoming obj cb = liftIO $ do let cb' = wrap_SocketServiceIncomingCallback cb cb'' <- mk_SocketServiceIncomingCallback cb' connectSignalFunPtr obj "incoming" cb'' SignalConnectBefore {- | Connect a signal handler for the “@incoming@” signal, to be run after the default handler. When is enabled, this is equivalent to @ 'Data.GI.Base.Signals.after' socketService #incoming callback @ -} afterSocketServiceIncoming :: (IsSocketService a, MonadIO m) => a -> SocketServiceIncomingCallback -> m SignalHandlerId afterSocketServiceIncoming obj cb = liftIO $ do let cb' = wrap_SocketServiceIncomingCallback cb cb'' <- mk_SocketServiceIncomingCallback cb' connectSignalFunPtr obj "incoming" cb'' SignalConnectAfter -- VVV Prop "active" -- Type: TBasicType TBoolean -- Flags: [PropertyReadable,PropertyWritable,PropertyConstruct] -- Nullable: (Nothing,Nothing) {- | Get the value of the “@active@” property. When is enabled, this is equivalent to @ 'Data.GI.Base.Attributes.get' socketService #active @ -} getSocketServiceActive :: (MonadIO m, IsSocketService o) => o -> m Bool getSocketServiceActive obj = liftIO $ B.Properties.getObjectPropertyBool obj "active" {- | Set the value of the “@active@” property. When is enabled, this is equivalent to @ 'Data.GI.Base.Attributes.set' socketService [ #active 'Data.GI.Base.Attributes.:=' value ] @ -} setSocketServiceActive :: (MonadIO m, IsSocketService o) => o -> Bool -> m () setSocketServiceActive obj val = liftIO $ B.Properties.setObjectPropertyBool obj "active" val {- | Construct a `GValueConstruct` with valid value for the “@active@” property. This is rarely needed directly, but it is used by `Data.GI.Base.Constructible.new`. -} constructSocketServiceActive :: (IsSocketService o) => Bool -> IO (GValueConstruct o) constructSocketServiceActive val = B.Properties.constructObjectPropertyBool "active" val #if ENABLE_OVERLOADING data SocketServiceActivePropertyInfo instance AttrInfo SocketServiceActivePropertyInfo where type AttrAllowedOps SocketServiceActivePropertyInfo = '[ 'AttrSet, 'AttrConstruct, 'AttrGet] type AttrSetTypeConstraint SocketServiceActivePropertyInfo = (~) Bool type AttrBaseTypeConstraint SocketServiceActivePropertyInfo = IsSocketService type AttrGetType SocketServiceActivePropertyInfo = Bool type AttrLabel SocketServiceActivePropertyInfo = "active" type AttrOrigin SocketServiceActivePropertyInfo = SocketService attrGet _ = getSocketServiceActive attrSet _ = setSocketServiceActive attrConstruct _ = constructSocketServiceActive attrClear _ = undefined #endif #if ENABLE_OVERLOADING instance O.HasAttributeList SocketService type instance O.AttributeList SocketService = SocketServiceAttributeList type SocketServiceAttributeList = ('[ '("active", SocketServiceActivePropertyInfo), '("listenBacklog", Gio.SocketListener.SocketListenerListenBacklogPropertyInfo)] :: [(Symbol, *)]) #endif #if ENABLE_OVERLOADING socketServiceActive :: AttrLabelProxy "active" socketServiceActive = AttrLabelProxy #endif #if ENABLE_OVERLOADING data SocketServiceIncomingSignalInfo instance SignalInfo SocketServiceIncomingSignalInfo where type HaskellCallbackType SocketServiceIncomingSignalInfo = SocketServiceIncomingCallback connectSignal _ obj cb connectMode = do let cb' = wrap_SocketServiceIncomingCallback cb cb'' <- mk_SocketServiceIncomingCallback cb' connectSignalFunPtr obj "incoming" cb'' connectMode type instance O.SignalList SocketService = SocketServiceSignalList type SocketServiceSignalList = ('[ '("event", Gio.SocketListener.SocketListenerEventSignalInfo), '("incoming", SocketServiceIncomingSignalInfo), '("notify", GObject.Object.ObjectNotifySignalInfo)] :: [(Symbol, *)]) #endif -- method SocketService::new -- method type : Constructor -- Args : [] -- Lengths : [] -- returnType : Just (TInterface (Name {namespace = "Gio", name = "SocketService"})) -- throws : False -- Skip return : False foreign import ccall "g_socket_service_new" g_socket_service_new :: IO (Ptr SocketService) {- | Creates a new 'GI.Gio.Objects.SocketService.SocketService' with no sockets to listen for. New listeners can be added with e.g. 'GI.Gio.Objects.SocketListener.socketListenerAddAddress' or 'GI.Gio.Objects.SocketListener.socketListenerAddInetPort'. New services are created active, there is no need to call 'GI.Gio.Objects.SocketService.socketServiceStart', unless 'GI.Gio.Objects.SocketService.socketServiceStop' has been called before. /Since: 2.22/ -} socketServiceNew :: (B.CallStack.HasCallStack, MonadIO m) => m SocketService {- ^ __Returns:__ a new 'GI.Gio.Objects.SocketService.SocketService'. -} socketServiceNew = liftIO $ do result <- g_socket_service_new checkUnexpectedReturnNULL "socketServiceNew" result result' <- (wrapObject SocketService) result return result' #if ENABLE_OVERLOADING #endif -- method SocketService::is_active -- method type : OrdinaryMethod -- Args : [Arg {argCName = "service", argType = TInterface (Name {namespace = "Gio", name = "SocketService"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GSocketService", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}] -- Lengths : [] -- returnType : Just (TBasicType TBoolean) -- throws : False -- Skip return : False foreign import ccall "g_socket_service_is_active" g_socket_service_is_active :: Ptr SocketService -> -- service : TInterface (Name {namespace = "Gio", name = "SocketService"}) IO CInt {- | Check whether the service is active or not. An active service will accept new clients that connect, while a non-active service will let connecting clients queue up until the service is started. /Since: 2.22/ -} socketServiceIsActive :: (B.CallStack.HasCallStack, MonadIO m, IsSocketService a) => a {- ^ /@service@/: a 'GI.Gio.Objects.SocketService.SocketService' -} -> m Bool {- ^ __Returns:__ 'True' if the service is active, 'False' otherwise -} socketServiceIsActive service = liftIO $ do service' <- unsafeManagedPtrCastPtr service result <- g_socket_service_is_active service' let result' = (/= 0) result touchManagedPtr service return result' #if ENABLE_OVERLOADING data SocketServiceIsActiveMethodInfo instance (signature ~ (m Bool), MonadIO m, IsSocketService a) => O.MethodInfo SocketServiceIsActiveMethodInfo a signature where overloadedMethod _ = socketServiceIsActive #endif -- method SocketService::start -- method type : OrdinaryMethod -- Args : [Arg {argCName = "service", argType = TInterface (Name {namespace = "Gio", name = "SocketService"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GSocketService", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}] -- Lengths : [] -- returnType : Nothing -- throws : False -- Skip return : False foreign import ccall "g_socket_service_start" g_socket_service_start :: Ptr SocketService -> -- service : TInterface (Name {namespace = "Gio", name = "SocketService"}) IO () {- | Restarts the service, i.e. start accepting connections from the added sockets when the mainloop runs. This only needs to be called after the service has been stopped from 'GI.Gio.Objects.SocketService.socketServiceStop'. This call is thread-safe, so it may be called from a thread handling an incoming client request. /Since: 2.22/ -} socketServiceStart :: (B.CallStack.HasCallStack, MonadIO m, IsSocketService a) => a {- ^ /@service@/: a 'GI.Gio.Objects.SocketService.SocketService' -} -> m () socketServiceStart service = liftIO $ do service' <- unsafeManagedPtrCastPtr service g_socket_service_start service' touchManagedPtr service return () #if ENABLE_OVERLOADING data SocketServiceStartMethodInfo instance (signature ~ (m ()), MonadIO m, IsSocketService a) => O.MethodInfo SocketServiceStartMethodInfo a signature where overloadedMethod _ = socketServiceStart #endif -- method SocketService::stop -- method type : OrdinaryMethod -- Args : [Arg {argCName = "service", argType = TInterface (Name {namespace = "Gio", name = "SocketService"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GSocketService", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}] -- Lengths : [] -- returnType : Nothing -- throws : False -- Skip return : False foreign import ccall "g_socket_service_stop" g_socket_service_stop :: Ptr SocketService -> -- service : TInterface (Name {namespace = "Gio", name = "SocketService"}) IO () {- | Stops the service, i.e. stops accepting connections from the added sockets when the mainloop runs. This call is thread-safe, so it may be called from a thread handling an incoming client request. Note that this only stops accepting new connections; it does not close the listening sockets, and you can call 'GI.Gio.Objects.SocketService.socketServiceStart' again later to begin listening again. To close the listening sockets, call 'GI.Gio.Objects.SocketListener.socketListenerClose'. (This will happen automatically when the 'GI.Gio.Objects.SocketService.SocketService' is finalized.) This must be called before calling 'GI.Gio.Objects.SocketListener.socketListenerClose' as the socket service will start accepting connections immediately when a new socket is added. /Since: 2.22/ -} socketServiceStop :: (B.CallStack.HasCallStack, MonadIO m, IsSocketService a) => a {- ^ /@service@/: a 'GI.Gio.Objects.SocketService.SocketService' -} -> m () socketServiceStop service = liftIO $ do service' <- unsafeManagedPtrCastPtr service g_socket_service_stop service' touchManagedPtr service return () #if ENABLE_OVERLOADING data SocketServiceStopMethodInfo instance (signature ~ (m ()), MonadIO m, IsSocketService a) => O.MethodInfo SocketServiceStopMethodInfo a signature where overloadedMethod _ = socketServiceStop #endif