Statistics
| Branch: | Tag: | Revision:

dvbd / src / outputbuffer.cpp @ e386e4be

History | View | Annotate | Download (2.63 KB)

1
/*
2
  Copyright 2003 John Knottenbelt
3
  
4
  This program is free software; you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation; either version 2 of the License, or
7
  (at your option) any later version.
8
 
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
 
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17
*/
18

    
19
#include "config.h"
20
#include "outputbuffer.h"
21
#include "dvbd.h"
22

    
23
#include <unistd.h>
24
#include <iostream>
25
#include <sys/types.h>
26
#include <sys/socket.h>
27
#include <sys/un.h>
28

    
29
OutputBuffer::OutputBuffer(int fd, int initSize, int maxSize)
30
  : CircularBuffer(initSize, maxSize), fd(fd)
31
{
32
}
33

    
34
OutputBuffer::~OutputBuffer()
35
{
36
}
37

    
38
void OutputBuffer::addSelectFDs(Select &s) const
39
{
40
  if (getUsed() > 0)
41
    s.addWriteFD(fd);
42
}
43

    
44
bool OutputBuffer::isReady(const Select &s) const
45
{
46
  return s.readyToWrite(fd);
47
}
48

    
49
bool OutputBuffer::process()
50
{
51
  if (getUsed() == 0)
52
    return true;
53

    
54
  // We are using a circular buffer. 
55
  // Write only the first half (if there is a second
56
  // half, we will get it next round).
57

    
58
  char *buffer1, *buffer2;
59
  int length1, length2;
60

    
61
  getSections(buffer1, length1, buffer2, length2);
62

    
63
  if (length1 == 0) {
64
    buffer1 = buffer2;
65
    length1 = length2;
66
  }
67

    
68
  int bytesWritten = ::write(fd, buffer1, length1);
69
  if (bytesWritten <= 0)
70
    return errno == EAGAIN;
71

    
72
  discard(bytesWritten);
73
  return true;
74
}
75

    
76
bool OutputBuffer::flush()
77
{
78
  // Flush the entire output buffer (blocking)
79
  Select s;
80

    
81
  while (getUsed() > 0) {
82
    addSelectFDs(s);
83
    s.wait();
84

    
85
    if (!isReady(s))
86
      return false;
87

    
88
    if (!process())
89
      return false;
90
    
91
    s.clearFDs();
92
  }
93
  return true;
94
}
95

    
96
bool OutputBuffer::writeCredentials()
97
{
98
  struct msghdr msg;
99
  char buffer[CMSG_SPACE(sizeof(struct ucred))];
100

    
101
  msg.msg_name = NULL;
102
  msg.msg_namelen = 0;
103
  msg.msg_iov = 0;
104
  msg.msg_iovlen = 0;
105
  msg.msg_control = buffer;
106
  msg.msg_controllen = sizeof(buffer);
107
  msg.msg_flags = 0;
108

    
109
  struct ucred ucred;
110
  ucred.pid = getpid();
111
  ucred.uid = getuid();
112
  ucred.gid = getgid();
113

    
114
  struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
115
  cmsg->cmsg_level = SOL_SOCKET;
116
  cmsg->cmsg_type = SCM_CREDENTIALS;
117
  cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
118
  memcpy(CMSG_DATA(cmsg), &ucred, sizeof(struct ucred));
119

    
120
  return sendmsg(fd, &msg, 0) >= 0;
121
}
122